I have a Dockerfile which installs production & test dependencies. I want to have separate image for tests, so production image is smaller, without to much code duplication. Maybe there is something like FROM
statement for referencing other Dockerfiles?
Dockerfile has following lines:
ADD requirements.txt ${PROJECT_DIR}/requirements.txt
RUN pip install --no-cache --process-dependency-links --trusted-host github.com -r requirements.txt
ADD requirements-test.txt ${PROJECT_DIR}/requirements-test.txt
RUN pip install --no-cache --process-dependency-links --trusted-host github.com -r requirements-test.txt
First two install depencencies for project, second two - install dependencies for testing (pytest, pylint, etc.).
I also have docker-compose that starts database, redis cache, etc. This is how I run service and run tests:
run:
docker-compose -f docker-compose.yaml run
test:
docker-compose -f docker-compose-dev.yaml run py.test tests/
Inside both docker-compose.yaml
has this build config for my container:
build:
context: .
dockerfile: ./Dockerfile
So, I could reference different Dockerfiles from my docker-compose.yaml
, but I don't want them to be complete copies that have only two lines difference.
The recommend method is multistage builds:
https://docs.docker.com/develop/develop-images/multistage-build/
That is dont separate production from test docker files. Instead keep all the requirements in one file and build for the target stage you need.
An example Dockerfile:
FROM python:3.8.7-slim-buster AS production
ADD requirements.txt ${PROJECT_DIR}/requirements.txt
RUN pip install -r requirements.txt
FROM production AS test
ADD requirements-test.txt ${PROJECT_DIR}/requirements-test.txt
RUN pip install -r requirements-test.txt
and then for your production build target the correct stage:
docker build --target production -t org/service:latest .
Multistage build syntax was introduced in Docker Engine 17.05.
FROM
is the way to go here. Production and Development images should not differ too much, or at all, since the idea is to deploy what you have developed. In my experience it is easier to start with a production image and extend a development image from that, since development requires more software like debuggers, compilers, etc.
Due to the comment:
Within a dockerfile
the FROM
directive takes an image tag, so something like ubuntu:latest
and than docker will first try to find that image locally and than try to pull it from a repo, if not.
In case you do not have a repo, you can create the base image locally by running:
docker build --tag vendor/production:0.0.1 .
what will compile the image. Than you can write:
FROM vendor/production:0.0.1
in your dev-dockerfile
and compile this. I usually create a tiny bash script for all the compilation stuff.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With