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

Optimizing Docker for IoT with Multi-Stage Builds

Tim Perry
December 14, 2017

Optimizing Docker for IoT with Multi-Stage Builds

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