230

I have multiple microservices and I am using docker-compose for development deployments. When there are some changes in the microservices code base, I am triggering ci job to re-deploy them. I have below script to do this. But each time I have to build all images from scratch, then run them. After all of this operation, I have anonymous images. So I am using the last script to remove them. What you would suggest making this process more practical? Is there any way to update an existing image without removing it with new changes?

- docker-compose build
- docker-compose down
- docker-compose up -d --force-recreate
- docker rmi $(docker images -f "dangling=true" -q) -f

Additional info: i am using gitlab-ci

Arty-chan
  • 2,572
  • 1
  • 19
  • 25
Efe
  • 5,180
  • 2
  • 21
  • 33

7 Answers7

307

Docker containers are designed to be ephemeral. To update an existing container, you remove the old one and start a new one. Thus the process that you are following is the correct one.

You can simplify the commands to the following ones:

docker-compose up --force-recreate --build -d
docker image prune -f
xdevs23
  • 3,824
  • 3
  • 20
  • 33
yamenk
  • 46,736
  • 10
  • 93
  • 87
  • 25
    You've missed off the -d flag in the docker-compose command; is that deliberate? – Vince Bowdren Mar 23 '18 at 17:19
  • 6
    I think the flag is important as not adding it will run everything in the foreground, killing off everything as soon as the session ends. Added it as many (most?) people will find `-d` useful/necessary. – xdevs23 May 02 '20 at 21:24
  • 61
    This appears to be missing the `docker-compose pull` step. `--force-recreate` doesn't pull updated images; it merely recreates the containers _even if the images haven't changed._ – Ryan Lue Mar 02 '21 at 18:54
  • 1
    just to make sure I understand, so I have to rebuild the images every update and wait for it again and again? – Ali Husham Jun 18 '21 at 14:33
  • 3
    All this did was reset my entire pi-hole to default settings and lose all my adlists, whitelists. `docker pull pihole/pihole:latest` would have been enough. – k4rli Nov 10 '21 at 10:32
  • 7
    @k4rli it sounds like you were storing all of your settings within the container itself, and not within an attached volume (which would have survived the removal of the container). Also, `docker pull` would not upgrade your running container—you'd still need to remove and recreate the container for the pull to take effect. – Alex Peters Feb 20 '22 at 00:42
241

You can update it using:

docker-compose pull

Now your image is updated. If you have the previous version of container running you should restart it to use the updated image:

docker-compose up --detach

up command automatically recreates container on image or configuration change.

Evgen Bodunov
  • 5,438
  • 2
  • 29
  • 43
  • Just running this didn't update the container for me. You're missing the part to rerun it. See https://stackoverflow.com/a/39501539/1452257 , which worked for me. – pir Oct 04 '19 at 17:57
  • @pir I've added clarification. – Evgen Bodunov Nov 14 '19 at 08:30
  • 27
    restart does not work because it won't recreate the container from the pull, you have to do `down` and `up -d` again. – Ciantic Mar 14 '20 at 20:34
  • 4
    In my case it recreates automatically. – Evgen Bodunov Mar 17 '20 at 09:06
  • 4
    I think a combination of @yamenk's comment and this one are the best way to go – xdevs23 Apr 20 '20 at 08:52
  • 1
    @EvgenBodunov "In my case it recreates automatically" This is the classic "Runs in my computer". Not very cool! – hoo2 Mar 23 '21 at 12:39
  • 7
    @hoo2 Do you wan't to make my answer better, please describe when container is updated from image automatically, and when it's not. I honestly don't know and can't improve the answer. "Not very cool!" is not cool itself. – Evgen Bodunov Mar 24 '21 at 13:06
  • Indeed, for me too, restart did not work. I had to do compose down, and up -d. Note running on centos 7.9 from official docker-ce repos. – ionescu77 May 10 '21 at 11:17
  • I believe the confusion comes from the effect, that `docker-compose up` without `down` only recreates containers for images that have changed (ie. new version is available). If you call `down` first, all containers are destroyed, therefore the `up` will recreate all of them. If your aim is only to update containers with the newest images, than `docker-compose up -d` is enough. If you need to recreate containers for any other reason, you need `docker-compose down` beforehand. – Bojan Hrnkas Mar 03 '23 at 05:51
191

I prefer to ensure all the images are downloaded before updating the containers with the new images to minimize the time in an intermediate state or worse being in the middle in case the download of an image fails.

  1. I pull latest images:

    docker-compose pull

  2. Then I restart containers:

    docker-compose up -d --remove-orphans

  3. Optionally, I remove obsolete images:

    docker image prune

danbtl
  • 84
  • 1
  • 10
Christophe Lallement
  • 2,017
  • 1
  • 10
  • 9
  • 21
    I like this answer, because it doesn't push to use `-f` or `--force-recreate`, which could have destructive side-effects. – kravemir Sep 05 '20 at 08:27
  • 5
    Here's a simple bash script so you can run it with a single command `./update-docker-compose-services.sh`: https://pastebin.com/EdDA5hZ2 – Wesley Egbertsen Nov 25 '21 at 22:07
  • I strugged for a while trying docker-compose commands, but when I finally switched to `docker compose pull` and `docker compose up` instead then it all went smoothly. Maybe something changed in the last two years for syntax on this answer? – Adam Nofsinger Jul 25 '22 at 14:46
  • @AdamNofsinger previously, "docker-compose" was a separate tool to "docker". Now, compose is part of docker so it is used as an argument to "docker"; I think most functionality should exist in the newer implementation and most commands you find online you can simply change "docker-compose" to "docker compose" and it should run as expected. YMMV – Freddy Grande Oct 04 '22 at 01:32
  • I edited the post to use the new style syntax. – Ben Randall Nov 13 '22 at 17:42
88
docker-compose pull

then

docker-compose up -d

you don't need "down" "docker-compose up -d" command will only recreate changed one

WhoSayIn
  • 4,449
  • 3
  • 20
  • 19
sonertbnc
  • 1,580
  • 16
  • 26
  • Simple and straightforward – Leafney Dec 04 '20 at 01:56
  • If you don't have any volumes its fine but if you do it will delete them. So actually it isn't an update. – chunk1ty Dec 29 '20 at 14:08
  • @chunk1ty please quote the docs where this is described. The `up` command help explicitely says "preserving mounted volumes" (see `docker-compose up --help`). `pull` doesn't even mentions volumes at all. – fklappan Jul 05 '21 at 19:11
  • Those two lines allow for partial upgrades, ie. only changed containers are stopped and upgraded. – makeroo Sep 06 '21 at 12:25
  • @makeroo what is a changed container ? I do have make changes to a container service files, now i,m stuck and don,t know how to upgrade that container with that changes or reflect that changes ? – Manifest Man Sep 18 '21 at 12:25
  • When you change the docker-compose.yml, modifying the version of the image in some container declaration, just calling "docker-compose up -d" triggers docker to stop and restart only those containers that have the version changed. It pulls new images too if needed, so you can just run "up" :-) – makeroo Sep 20 '21 at 09:21
3

With docker-compose version 3 you can add tags to your images and clean up by them depends on your logic:

build: ./dir
image: yourapp:tag

It could help you to avoid anonymous images to clean up

AlexGera
  • 756
  • 9
  • 19
3

I've noticed above answers, but I still insist to use the following orders to make sure everything is correct:

  1. docker-compose pull
  2. docker-compose down
  3. docker-compose up -d
Zhang Buzz
  • 10,420
  • 6
  • 38
  • 47
2

There is also a script, with which one can update many docker-compose stacks at once.

It is called compose-update and can be found at the following link:

https://github.com/FrederikRogalski/compose-update

compose-update a docker-compose-image-updater

This python script updates the images of one or many docker-compose stacks automatically.

If multiple docker-compose directories are supplied, the script updates them in parallel.

Demo

output

Usage

Usage: compose-update [OPTIONS] [UPDATE_DIRS]...

  Update docker-compose images automatically.

  Takes one or more directorys as input and searches for a
  compose file in one of the following forms:
  "compose.yaml", "compose.yml", "docker-compose.yaml",
  "docker-compose.yml"

Options:
  --prune / --no-prune  Prune docker images after update
                        process if set
  --help                Show this message and exit.

Installation

git clone https://github.com/FrederikRogalski/compose-update.git
cd compose-updater
chmod +x update-compose

Then add the file 'update-compose' to your path.

Gunar Gessner
  • 2,331
  • 23
  • 23