Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Optimizing Docker for IoT with Multi-Stage Builds

Avatar for Tim Perry Tim Perry
December 14, 2017

Optimizing Docker for IoT with Multi-Stage Builds

Avatar for Tim Perry

Tim Perry

December 14, 2017
Tweet

More Decks by Tim Perry

Other Decks in Technology

Transcript

  1. Lightweight OS for IoT with Docker Optimised support for 25+

    boards Preconfigured flexible networking support Secure by default throughout Read-only root partition + AUFS data partition @pimterry
  2. @pimterry Moby-based container engine for IoT Fully Docker-compatible 3.5x smaller

    than Docker 10-70x more bandwidth efficient ‘docker pull’ Built for low-memory environments Atomic & durable pulls
  3. FROM node:8 ARG NPM_TOKEN RUN echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc &&

    \ npm whoami RUN mkdir -p /usr/src/app WORKDIR /usr/src/app COPY . . RUN npm install && npm run build && rm ~/.npmrc CMD [ "/usr/local/bin/node", "./built.js" ] @pimterry The Problem
  4. FROM node:8 ARG NPM_TOKEN RUN echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc &&

    \ npm whoami RUN mkdir -p /usr/src/app WORKDIR /usr/src/app COPY . . RUN npm install && npm run build && rm ~/.npmrc CMD [ "/usr/local/bin/node", "./built.js" ] @pimterry The Problem 700MB image (for an empty project)
  5. FROM node:8 ARG NPM_TOKEN RUN echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc &&

    \ npm whoami RUN mkdir -p /usr/src/app WORKDIR /usr/src/app COPY . . RUN npm install && npm run build && rm ~/.npmrc CMD [ "/usr/local/bin/node", "./built.js" ] @pimterry The Problem
  6. ➜ docker image inspect 274627c8a3a2 [ { "Id": "sha256:274627c8a3a28d...", ...

    "GraphDriver": { "Data": { "LowerDir": "...", "MergedDir": "/var/lib/docker/overlay2/61038f.../merged", "UpperDir": "/var/lib/docker/overlay2/61038f.../diff", "WorkDir": "/var/lib/docker/overlay2/61038f.../work" }, }, } ] @pimterry The Problem
  7. ➜ docker history e5936788a37a IMAGE CREATED CREATED BY SIZE e5936788a37a

    2 minutes ago /bin/sh -c #(nop) CMD ["/usr/local/bin/no... 0B 79fad4492e73 2 minutes ago |1 NPM_TOKEN= <!!!!!!!secret token!!!!!!!>... 537kB 373ea011abf1 2 minutes ago /bin/sh -c #(nop) COPY dir:6ffc7f0ac3036c2... 459B 155133064e6a 2 minutes ago /bin/sh -c #(nop) WORKDIR /usr/src/app 0B 2a5d69935132 2 minutes ago |1 NPM_TOKEN= <!!!!!!!secret token!!!!!!!>... 0B 274627c8a3a2 2 minutes ago |1 NPM_TOKEN= <!!!!!!!secret token!!!!!!!>... 125B 8f14bc306cc4 3 minutes ago /bin/sh -c #(nop) ARG NPM_TOKEN 0B 2eeae8debf3d 2 days ago /bin/sh -c #(nop) CMD ["node"] 0B <missing> 2 days ago /bin/sh -c set -ex && for key in 6A0... 4.17MB <missing> 2 days ago /bin/sh -c #(nop) ENV YARN_VERSION=1.3.2 0B <missing> 2 days ago /bin/sh -c ARCH= && dpkgArch="$(dpkg --pri... 56.6MB <missing> 2 days ago /bin/sh -c #(nop) ENV NODE_VERSION=8.9.3 0B <missing> 2 days ago /bin/sh -c set -ex && for key in 94A... 129kB ... @pimterry The Problem
  8. @pimterry --squash Limitations Requires ‘experimental’ flag Silent disaster if you

    forget to squash Can be less efficient Doesn’t erase history
  9. Rename previous Dockerfile to Dockerfile.build docker build . -f Dockerfile.build

    Copy build output from image to local file with docker cp Build production Dockerfile ⟶ @pimterry Builder Pattern Dockerfile: FROM node:8-alpine RUN mkdir -p /usr/src/app WORKDIR /usr/src/app COPY ./built.js . CMD [ "/usr/local/bin/node", "./built.js" ]
  10. FROM base as build-stage ... FROM build-stage as test-stage ...

    FROM build-stage @pimterry Change default target:
  11. FROM node:8 AS build ARG NPM_TOKEN RUN echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >>

    ~/.npmrc && \ npm whoami RUN mkdir -p /usr/src/app WORKDIR /usr/src/app COPY . . RUN npm install && npm run build CMD [ "/usr/local/bin/node", "./built.js" ] FROM node:8-alpine RUN mkdir -p /usr/src/app WORKDIR /usr/src/app COPY --from=build /usr/src/app/built.js . CMD [ "/usr/local/bin/node", "./built.js" ] @pimterry Fixed Multi-Stage Dockerfile
  12. FROM node:8 AS build ARG NPM_TOKEN RUN echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >>

    ~/.npmrc && \ npm whoami RUN mkdir -p /usr/src/app WORKDIR /usr/src/app COPY . . RUN npm install && npm run build CMD [ "/usr/local/bin/node", "./built.js" ] FROM node:8-alpine RUN mkdir -p /usr/src/app WORKDIR /usr/src/app COPY --from=build /usr/src/app/built.js . CMD [ "/usr/local/bin/node", "./built.js" ] @pimterry Fixed Multi-Stage Dockerfile 70MB image (90% smaller)
  13. IMAGE CREATED CREATED BY SIZE 0e1999330a57 5 seconds ago /bin/sh

    -c #(nop) CMD ["/usr/local/bin/no... 0B bdd51c6251d5 6 seconds ago /bin/sh -c #(nop) COPY file:19fa00c24fa256... 614kB fadd597467a6 6 seconds ago /bin/sh -c #(nop) WORKDIR /usr/src/app 0B e7bffff20b93 6 seconds ago /bin/sh -c mkdir -p /usr/src/app 0B 144aaf4b1367 5 days ago /bin/sh -c #(nop) CMD ["node"] 0B <missing> 5 days ago /bin/sh -c apk add --no-cache --virtual .b... 4.19MB <missing> 5 days ago /bin/sh -c #(nop) ENV YARN_VERSION=1.3.2 0B <missing> 5 days ago /bin/sh -c addgroup -g 1000 node && ad... 59.6MB <missing> 5 days ago /bin/sh -c #(nop) ENV NODE_VERSION=8.9.3 0B <missing> 12 days ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B <missing> 12 days ago /bin/sh -c #(nop) ADD file:cb381165dec3689... 3.97MB @pimterry Hide secure credentials: Secrets don’t appear in the history Previous stage layers are separate
  14. @pimterry Take huge images: FROM ekidd/rust-musl-builder ADD . ./ RUN

    sudo chown -R rust:rust /home/rust RUN cargo build --release EXPOSE 8000 CMD ["/home/rust/src/.../rust-server"] Resulting image: 2.3 GB github.com/pimterry/multistage-demos/tree/master/rust-server
  15. @pimterry Build tiny images: FROM ekidd/rust-musl-builder as build ADD .

    ./ RUN sudo chown -R rust:rust /home/rust RUN cargo build --release FROM scratch COPY --from=build /home/rust/src/.../rust-server / EXPOSE 8000 CMD ["/rust-server"] Resulting image: 4.8 MB github.com/pimterry/multistage-demos/tree/master/rust-server
  16. Multi-stage builds let you: Control image history Control image size

    Declaratively describe your build @pimterry