Rex Roof I come from the land of ice and snow. I think about, read about, construct, and eat good food. Using Unix for 25 years. Platform Architect at Blue Newt Software ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●
Blue Newt Software Startup Studio - we help you create modern software. Working with auto manufacturers, sports leagues, agriculture. We also build and sell our own software. I get to start new projects a few times a year. (and see the same mistakes) ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●
What is a Docker container? A way to isolate and package software. A method for wrapping up a single process into a deployable object. Every container should have a single responsibility. A Dockerfile defines a container with a series of instructions. Docker containers are stored in filesystem layers. ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●
Cached layers are your friend They don’t need to be built again when you’re developing. They don’t need to be uploaded to a registry. They don’t need to be stored in the registry. They don’t need to be downloaded on your deployment server. ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●
Choose a smaller base image Start small, install what you need. Alpine is small, but use with caution. libc and DNS issues can arise. Spend the time early on to find the right container base and iterate. You have tests, right? ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●
Leverage multi-stage builds - Define multiple docker containers in one Dockerfile - Builds each in order, using the final container in the image - Copy files between containers - You can target individual containers when building ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●
Using multi-stage builds ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● FROM golang:alpine as build COPY hello.go . RUN go build -o hello hello.go # above is ~350MB FROM alpine as alpine-run COPY --from=build /go/hello /hello CMD ["/hello"] # above is ~7MB - Only your target or final stage is saved in your image. - Each layer still caches locally - Can target higher layers using docker build --target=NAME
Using multi-stage builds ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● # development container FROM node:12.14.1-alpine as development WORKDIR /app ENV HOME /app COPY yarn.lock package.json /app/ RUN npm install COPY public/ /app/public/ COPY src/ /app/src/ EXPOSE 3000 CMD ["npm", "start"] # temp build container FROM development as build ARG NODE_ENV=production ARG GENERATE_SOURCEMAP=false RUN npm run build # production container FROM nginx:1.17.8-alpine as production COPY --from=build /app/build /usr/share/nginx/html
Learn your language packaging options PYTHONDONTWRITEBYTECODE=1 pip install --no-cache-dir python: don’t write cache, don’t create python byte code npm ci --production nodejs: install only production packages, no dev dependencies bundle install --deployment ruby: roll out packages for CI or production use ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●
The Docker mindset No longer setting up long-running servers Thinking more about the full lifecycle. Automating your software setup. ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●
Takeaways - Make your containers smaller - Rearrange your Dockerfile to optimize layers - Review your .dockerignore files - Respect the layer cache - Your container is not a VM github.com/rexroof/docker-weight-loss ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●