skip to Main Content

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


  1. 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.

    Login or Signup to reply.
  2. You can try pulling images by its digest

    For instance

    docker pull mysql:latest
    latest: Pulling from library/mysql
    ...
    Digest: sha256:548da4c67fd8a71908f17c308b8ddb098acf5191d3d7694e56801c6a8b2072cc
    Status: Downloaded newer image for mysql:latest
    docker.io/library/mysql:latest
    

    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.

    docker pull mysql@sha256:548da4c67fd8a71908f17c308b8ddb098acf5191d3d7694e56801c6a8b2072cc
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search