Home > Software design >  Docker Compose - Is it possible to update all changed images with a single command?
Docker Compose - Is it possible to update all changed images with a single command?

Time:10-21

I have a compose.yml like this one:

version: '3.7'

services:
    nginx:
        restart: unless-stopped
        image: ghcr.io/user/frontend:latest
        ports:
            - 80:80
        depends_on: 
            - backend
    backend:
        restart: unless-stopped
        image: ghcr.io/user/backend:latest
        entrypoint: /home/app/web/wsgi-entrypoint.sh
        expose:
            - 8000   

We have 2 images stored on Github: frontend and backend.

My goal is the following: when an image has been updated on the Github Docker Registry, I'd like to automatically update the image on the server and launch the new one substituting the old one via docker-compose.

For example: I have a running compose made by frontend and backend, but I just pushed a new image: ghcr.io/user/frontend:latest.

Now, I want a single command which updates only the images that have been changed (in this case ghcr.io/user/frontend:latest) and when I reload the frontend webpage I see the changes.

My attempt is the following:

docker-compose up -d --build

But the system says:

compose-backend_1 is up-to-date
compose-nginx_1 is up-to-date

which is not true!

So, the working procedure I use is a bit manual:

docker pull ghcr.io/user/frontend:latest

I see in the console: Status: Downloaded newer image, which is the proof that a new image has been downloaded. Then, if I relaunch the same command the console displays: Status: Image is up to date for ghcr.io/user/frontend:latest

Finally:

docker-compose up -d --build

says: Recreating compose-nginx_1 ... done

I suppose the command docker-compose up -d --build ALONE is not looking for new images and so does not update the image that is changed.

So, is there a SINGLE specific command to fix this?

CodePudding user response:

Should be achieved by running docker-compose pull, and then docker-compose up -d Or, shorter: docker-compose up -d --pull always

CodePudding user response:

You can use variable substitution in many places in a docker-compose.yml file, in particular including the image:. If you give every build a unique tag, then you can supply the tag as an environment variable, and it will work the way you describe.

Let's say the two images have the same tagging scheme (they don't necessarily need to). You could update the Compose file to say

version: '3.8'
services:
    nginx:
        restart: unless-stopped
        image: ghcr.io/user/frontend:${TAG:-latest} # <--
        ports:
            - 80:80
        depends_on: 
            - backend
    backend:
        restart: unless-stopped
        image: ghcr.io/user/backend:${TAG:-latest} # <--

Notice the $TAG reference at the end of the image: lines. If TAG isn't set in the environment, it will use latest, but if it is, it will use that exact build.

Now, if I run:

TAG=20221020 docker-compose up -d

For both containers, Compose will notice that they're running an older build, automatically pull the updated image from GitHub, and restart both containers against the newer image.

This brings the mild complication of your continuous-deployment system needing to know the current image tag. In exchange, though, you get the ability to very easily roll back – if today's build turns out to have a critical bug you can run the exact same command with a different tag to redeploy on yesterday's build. A setup like this is also necessary if you're considering migrating to Kubernetes, since it depends on the text of the image: string changing to trigger a redeployment.

  • Related