I am working on a Docker project and would like to create a reproducible build. In other words, I would like to specify in my .yml file the exact version of each dependency I would like to use. I understand there are tags, but it looks like tags are not necessarily stable (i.e. a tag can be updated, and therefore, by using the tag I’m not guaranteed to get the same version over time).
According to this tags can be updated/replaced/changed:
https://www.howtogeek.com/devops/how-to-add-replace-and-remove-docker-image-tags/
Specifically, I’m working with this codebase:
https://github.com/data61/anonlink-entity-service
And this .yml file:
https://github.com/data61/anonlink-entity-service/blob/develop/tools/docker-compose.yml
And would like to use a stable (unchanging) version of this: data61/anonlink-app
The existing codebase uses this for the version: image: data61/anonlink-app:${TAG:-latest}
Which is also problematic as it is likely to change as well as for a number of other reasons described here: https://medium.com/@mccode/the-misunderstood-docker-tag-latest-af3babfd6375
Full .yml file is shown below
version: '3.4'
services:
db:
image: postgres:11.13
environment:
- POSTGRES_PASSWORD=rX%QpV7Xgyrz
volumes:
- psql:/var/lib/postgresql/data
#ports:
#- 5432:5432
healthcheck:
test: pg_isready -q -h db -p 5432 -U postgres
interval: 5s
timeout: 30s
retries: 5
minio:
image: minio/minio:RELEASE.2021-02-14T04-01-33Z
command: server /export
env_file:
- .env
volumes:
- minio:/export
ports:
- 9000:9000
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
redis:
image: redis:5.0
# The flask application server
backend:
image: data61/anonlink-app:${TAG:-latest}
env_file:
- .env
environment:
- FLASK_DB_MIN_CONNECTIONS=1
- FLASK_DB_MAX_CONNECTIONS=10
depends_on:
- db
- db_init
- redis
- minio
- objectstore_init
# The application server can also setup the database
db_init:
image: data61/anonlink-app:${TAG:-latest}
environment:
- DEBUG=true
- DATABASE_PASSWORD=rX%QpV7Xgyrz
- FLASK_APP=entityservice
entrypoint: /bin/sh -c "dockerize -wait tcp://db:5432 alembic upgrade head"
depends_on:
- db
# Set up the object store to have another more restricted user
objectstore_init:
image: minio/mc:RELEASE.2021-02-14T04-28-06Z
environment:
- OBJECT_STORE_SECURE=false
env_file:
- .env
entrypoint: |
/bin/sh /opt/init-object-store.sh
volumes:
- ./init-object-store.sh:/opt/init-object-store.sh:ro
depends_on:
- minio
# A celery worker
worker:
image: data61/anonlink-app:${TAG:-latest}
depends_on:
- redis
- db
command: celery -A entityservice.async_worker worker --loglevel=info -O fair -Q celery,compute,highmemory
env_file:
- .env
environment:
- CELERY_ACKS_LATE=true
- REDIS_USE_SENTINEL=false
- CELERYD_MAX_TASKS_PER_CHILD=2048
#- CHUNK_SIZE_AIM=300_000_000
- CELERY_DB_MIN_CONNECTIONS=1
- CELERY_DB_MAX_CONNECTIONS=3
nginx:
image: data61/anonlink-nginx:${TAG:-latest}
ports:
- 8851:8851
depends_on:
- backend
environment:
TARGET_SERVICE: backend
PUBLIC_PORT: 8851
# A celery monitor. Useful for debugging.
# celery_monitor:
# image: data61/anonlink-app:${TAG:-latest}
# depends_on:
# - redis
# - worker
# command: celery flower -A entityservice.async_worker
# ports:
# - 8888:8888
# Jaeger UI is available at http://localhost:16686
jaeger:
image: jaegertracing/all-in-one:latest
environment:
COLLECTOR_ZIPKIN_HTTP_PORT: 9411
# ports:
# - 5775:5775/udp
# - 6831:6831/udp
# - 6832:6832/udp
# - 5778:5778
# - 16686:16686
# - 14268:14268
# - 9411:9411
volumes:
psql:
minio:
2
Answers
If you don’t have control on the dependencies, then you cannot guarantee the images will be the same indeed.
What you can do is to fork the projects of those dependencies and create the images yourself, or have your own container registry from which you pull images, and there push the images of the dependencies you want to keep.
You can try pulling images by its digest
For instance
In the future
latest
tag will point to another image (newer mysql version, patched server …) but its digests will point to this exactly version. As it is a hash of the content, you will get the same image for sure.So pull the image using its sha256 hash instead of a volatile tag.