Search code examples
dockerdocker-composedocker-machinedockerhub

Building a Docker image and pushing to a image/container registry using docker-compose


I have the following docker-compose.yml file:

docker-compose.staging.yml:

version: '3.7'

services:
  web:
    restart: always
    build: ./django
    expose:
      - "8000"
    volumes:
      - django-static:/usr/src/app/static
      - django-uploads:/usr/src/app/uploads
    environment:
      DJANGO_POSTGRES_REMOTE: 'True'
      DJANGO_POSTGRES_HOST: myservername.postgres.database.azure.com
      DJANGO_POSTGRES_PORT: '1234'
      DJANGO_POSTGRES_NAME: dbname
      DJANGO_POSTGRES_USER: dbuser
      DJANGO_POSTGRES_PASS: dbpassword
      DJANGO_SECRET_KEY: 
      DJANGO_DEBUG: 1
      DJANGO_TESTING: 0
      DJANGO_WAVE_API_VERSION: '1'
      DJANGO_WAVE_SUPERUSER_USERNAME: ''
      DJANGO_WAVE_SUPERUSER_PASSWORD: ''
      DJANGO_WAVE_SUPERUSER_EMAIL: ''
      DJANGO_BUGSNAG_LOGGING_ENABLED: 0
      DJANGO_BUGSNAG_API_KEY: ''
      DJANGO_ROOT_DOMAIN: ''
      DJANGO_MEMCACHED_ON: 'False'
      VUE_ROOT_DOMAIN: ''

    command: /usr/src/app/wave.sh

  nginx:
    build:
      context: nginx
      dockerfile: Dockerfile
    restart: on-failure
    ports:
      - 80:80
      - 443:443
    volumes:
      - ssl_data:/etc/resty-auto-ssl
    environment:
      ALLOWED_DOMAINS: "${STAGING_ALLOWED_DOMAINS}"
      SITES: "${STAGING_SITES}"

volumes:
  ssl_data:
  django-static:
  django-uploads:

I have tested this docker-compose file build process with the code, and all deploys fine:

docker-compose -f docker-compose.staging.yml up --build

My question is, I usually deploy automatically using docker-machine, which deploys a new virtual machine.

However, I am wondering, what is the procedure with docker-compose to publish this as an image to a Docker registry like Docker Hub? I have tried to search for an answer, but there doesn't seem to be anything that I can find.

Do I build two images from both services?

Is it possible to push two or more services from a docker-compose.yml file to Docker Hub (or similar)?


Solution

  • The Docker Compose YAML file you show builds two separate images from two separate Dockerfiles, then runs one container from each. You can use docker push or docker-compose push to push the individual images to Docker Hub, but there's no way to combine these into a single image or to push this entire deployment setup as a unit.

    The setup you'll wind up with when you go to run these two images will need a very similar docker-compose.yml file, but with image: lines instead of build:

    version: '3.7'
    services:
      web:
        restart: always
        image: myname/web:20191129
        volumes: [ ... ]
        environment: { ... }
      nginx:
        image: myname/nginx:20191129
        restart: on-failure
        ports: ['80:80', '443:443']
        volumes: [ ... ]
        environment: { ... }
    volumes: { ... }
    

    (The volumes:, ports:, and environment: are the same as in your original file; expose: and command: should probably be built into the image and don't need to be repeated.)

    Check this file into source control. You can distribute it to the target system however you'd like: manually scp it, or use an automation tool like Ansible or Chef to put it there and launch it.

    To get the images pushed to Docker Hub (or another registry) you need a Docker Compose file with both build: and image:. If you specify both, then when you docker-compose build the images, they will get tagged with the name you specify. You can then docker-compose push both images (with one command, but still as two separate images).

    In this environment you also might find it helpful to have multiple overlapping docker-compose.yml files. Make the base docker-compose.yml file only have the image: declarations, and add a separate docker-compose.build.yml

    version: '3'
    services:
      web:
        build: ./django
        # and no other options
      nginx:
        build: ./nginx
    

    Then when you want to build the image for pre-deployment testing or to push it you can

    docker-compose -f docker-compose.yml -f docker-compose.build.yml build