Instead of using --squash, you can use Docker multi-stage builds.
Here is a simple example for a Python app that uses the Django web framework. We want to separate out the testing dependencies into a different image, so that we do not deploy the testing dependencies to production. Additionally, we want to separate our automated documentation utilities from our test utilities.
Here is the Dockerfile:
# the AS keyword lets us name the image
FROM python:3.6.7 AS base
WORKDIR /app
RUN pip install django
# base is the image we have defined above
FROM base AS testing
RUN pip install pytest
# same base as above
FROM base AS documentation
RUN pip install sphinx
In order to use this file to build different images, we need the --target flag for docker build. The argument of --target should name the name of the image after the AS keyword in the Dockerfile.
Build the base image:
docker build --target base --tag base .
Build the testing image:
docker build --target testing --tag testing .
Build the documentation image:
docker build --target documentation --tag documentation .
This lets you build images that branch from the same base image, which can significantly reduce build-time for larger images.
You can also use multi-stage builds in Docker Compose. As of version 3.4 of docker-compose.yml, you can use the target keyword in your YAML.
Here is a docker-compose.yml file that references the Dockerfile above:
version: '3.4'
services:
testing:
build:
context: .
target: testing
documentation:
build:
context: .
target: documentation
If you run docker-compose build using this docker-compose.yml, it will build the testing and documentation images in the Dockerfile. As with any other docker-compose.yml, you can also add ports, environment variables, runtime commands, and so on.