Docker-first Python development (2019-04-12)

Except there’s one thing still bothering me: changes to the service code trigger a reinstallation of our test dependencies.

Yuck! Let’s take another whack at our Dockerfile

 1 FROM python3 as service_deps
 2 COPY requirements.txt ./
 3 RUN pip install -r requirements.txt
 4
 5 FROM deps as test_deps
 6 COPY test_requirements.txt ./
 7 RUN pip install -r test_requirements.txt
 8
 9 FROM deps as builder
10 COPY src ./src
11
12 FROM test_deps as tests_builder
13 COPY src ./src
14 COPY tests ./tests
15
16 FROM tests_builder as localdev
17 ENTRYPOINT ["pytest"]
18 CMD ["tests"]
19
20 FROM tests_builder as tests
21 RUN pytest tests
22
23 FROM builder as service
24 COPY docker-entrypoint.sh ./
25 ENTRYPOINT ["docker-entrypoint.sh"]
26 EXPOSE 3000

Ok that seems pretty complicated, here’s a graph of our image topology:

service_deps
   |   \
   |    -\
   |      \
   |       -test_deps
   |            |
   |            |
builder     tests_builder
   |            |  -\
   |            |    -\
   |        localdev   -\
   |                     --tests
service

I don’t love that the builder and tests_builder stages both copy over the source directory, but the real question is, does this still meet our initial goals while avoiding excessive re-installs of test dependencies ?

Yeah, it seems to work pretty well.

Thanks to Docker’s layer caching, we rarely have to re-install dependencies.