204

I don't know what I'm doing wrong, but I simply cannot get docker-compose up to use the latest image from our registry without first removing the old containers from the system completely. It looks like compose is using the previously started image even though docker-compose pull has fetched a newer image.

I looked at How to get docker-compose to always re-create containers from fresh images? which seemed to be similar to my issue, but none of the provided solutions there work for me, since I'm looking for a solution I can use on the production server and there I don't want to be removing all containers before starting them again (possible data loss?). I would like for compose only to detect the new version of the changed images, pull them and then restart the services with those new images.

I created a simple test project for this in which the only goal is to get a version nr to increase on each new build. The version nr is displayed if I browse to the nginx server that is created (this works as expected locally).

docker version: 1.11.2 docker-compose version: 1.7.1 OS: tested on both CentOS 7 and OS X 10.10 using docker-toolbox

My docker-compose.yml:

version: '2'
services:
  application:
    image: ourprivate.docker.reg:5000/ourcompany/buildchaintest:0.1.8-dev
    volumes:
      - /var/www/html
    tty: true

  nginx:
    build: nginx
    ports:
      - "80:80"
    volumes_from:
      - application
    volumes:
      - ./logs/nginx/:/var/log/nginx
  php:
    container_name: buildchaintest_php_1
    build: php-fpm
    expose:
      - "9000"
    volumes_from:
      - application
    volumes:
      - ./logs/php-fpm/:/var/www/logs

on our jenkins server I run the following to build and tag the image

cd $WORKSPACE && PROJECT_VERSION=$(cat VERSION)-dev
/usr/local/bin/docker-compose rm -f
/usr/local/bin/docker-compose build
docker tag ourprivate.docker.reg:5000/ourcompany/buildchaintest ourprivate.docker.reg:5000/ourcompany/buildchaintest:$PROJECT_VERSION
docker push ourprivate.docker.reg:5000/ourcompany/buildchaintest

this seems to be doing what it's supposed to be since I get a new version tag in our repository each time the build completes and the version nr has been bumped.

If I now run

docker-compose pull && docker-compose -f docker-compose.yml up -d

in a folder on my computer, where the contents is only the docker-compose.yml and the necessary Dockerfiles to build the nginx and php services, the output I get is not the latest version number as has been tagged in the registry or is shown in the docker-compose.yml (0.1.8), but the version before that, which is 0.1.7. However the output of the pull command would suggest that a new version of the image was fetched:

Pulling application (ourprivate.docker.reg:5000/ourcompany/buildchaintest:latest)...
latest: Pulling from ourcompany/buildchaintest
Digest: sha256:8f7a06203005ff932799fe89e7756cd21719cccb9099b7898af2399414bfe62a
Status: Downloaded newer image for docker.locotech.fi:5000/locotech/buildchaintest:0.1.8-dev

Only if I run

docker-compose stop && docker-compose rm -f

and then run the docker-compose up command do I get the new version to show up on screen as expected.

Is this intended behaviour of docker-compose? i.e. should I always do a docker-compose rm -f before running up again, even on production servers? Or am I doing something against the grain here, which is why it's not working?

The goal is to have our build process build and create tagged versions of the images needed in a docker-compose.yml, push those to our private registry and then for the "release to production-step" to simply copy the docker-compose.yml to the production server and run a docker-compose pull && docker-compose -f docker-compose.yml up -d for the new image to start in production. If anyone has tips on this or can point to a best practices tutorial for this kind of setup that would be much appreciated also.

Community
  • 1
  • 1
Jens Wegar
  • 4,147
  • 4
  • 29
  • 34
  • 4
    `docker-compose up -d --force-recreate` didn't work? – BMitch Jun 07 '16 at 22:04
  • To avoid the risk of data loss when removing/recreating containers, use a host or named volume. It looks like you are already using host volumes for the other containers. An empty named volume will initialize with the contents of the image's volume when you first use it. – BMitch Jun 07 '16 at 22:07
  • 2
    --force-recreated didn't work, no :( I'm using volumes for data storage, so the data loss part is perhaps not that relevant. But I'm still confused as to having to do a docker-compose rm before re-starting the containers. Shouldn't the up, command, especially with force-recreate, take care of notificing a new image an using that instead? It feels wrong that I'd have to force a removal on a production server – Jens Wegar Jun 08 '16 at 09:14
  • If `--force-recreate` isn't recreating the containers, then you might need to file a bug report on `docker-compose`. Keep in mind that using a new image would be recreating the container, which would remove it. And if you don't remove any container specific volumes in the process, you can get a rather long dangling list of data you never use again in `docker volume ls -f dangling=true`. So your fix is the first half of what docker-compose should be doing for you. – BMitch Jun 08 '16 at 11:01
  • Ok, thank you! I'll have to fiddle around a bit more to make sure I understand the process (still a newbie when it comes to Docker), but looks like docker-compose rm -f before building is what I'll need to do then. – Jens Wegar Jun 09 '16 at 05:49

17 Answers17

135

in order to make sure, that you are using the latest version for your :latest tag from your registry (e.g. docker hub) you need to also pull the latest tag again. in case it changed, the diff will be downloaded and started when you docker-compose up again.

so this would be the way to go:

docker-compose stop
docker-compose rm -f
docker-compose pull   
docker-compose up -d

i glued this into an image that i run to start docker-compose and make sure images stay up-to-date: https://hub.docker.com/r/stephanlindauer/docker-compose-updater/

stephanlindauer
  • 1,910
  • 2
  • 14
  • 17
  • 173
    `docker-compose pull && docker-compose up -d` is enough. It automatically checks if the running containers are outdated and if that's the case, recreates them with the newest images – Mindaugas Varkalys Apr 01 '20 at 10:10
  • 1
    @MindaugasVarkalys That works on Linux, but not on Mac, unless you add `--force-recreate` option. – Ömer An Mar 18 '22 at 17:08
  • Same is true for pull_policy: always. It's implemented on Mac, and pulls the image, but doesn't replace the running container. – Dan Caseley Apr 01 '22 at 16:29
  • 1
    @MindaugasVarkalys asnwer's should be the accepted answer – Niv Jul 27 '22 at 09:21
  • 2
    This should **not** be accepted solution as it maximize downtime. pull is long and can fail and can be done in advance without disturbing the service. – Setop Feb 24 '23 at 06:03
57

To get the latest images use docker-compose build --pull

I use below command which is really 3 in 1

docker-compose down && docker-compose build --pull && docker-compose up -d

This command will stop the services, pulls the latest image and then starts the services.

Grez
  • 306
  • 3
  • 8
Abhishek Galoda
  • 2,753
  • 24
  • 38
  • 2
    Maybe you should add `docker-compose pull` to update images for services with image: instead of build: in `docker-compose.yml` or will `docker-compose build --pull` do this? – oceanBT Apr 29 '20 at 11:11
  • 1
    I get `nginx uses an image, skipping` when using docker-compose build --pull Thus is not updating the images. – Antonio Aug 19 '20 at 10:56
  • 2
    Do not use this command! Or at least be careful and know what you do.. `docker-compose down` will remove all anonymous volumes and can result in loosing data if you have a database in your dokcer-compose.yml! – H4kor Jan 12 '22 at 08:36
50

I use the following even if my container is running and it updates just fine.

docker-compose pull
docker-compose up -d
  • 1
    It works fine but you can end up with *"no space left on device"* errors on small machines as Docker will keep old image layers of running containers, even with a call to `docker system prune`. – AymDev Sep 16 '21 at 14:54
  • Use `docker system prune -af` to force remove ALL dangling containers and obsolete image layers. Not using `-a` is usually quite effective however depending on your process a lot of containers may be left 'dangling' and as such not considered for cleanup by default. This does make `-a` theoretically dangerous so check what you're doing, it *will* trash containers, images and volumes if a Compose set is temporarily down during prune. – Niels Keurentjes Feb 01 '23 at 09:47
40

[EDIT] DO NOT USE
The below is in the spec but, as pointed out in the comments, has not been implemented yet (docker-compose 1.29.2 and 2).

Since 2020-05-07, the docker-compose spec also defines the "pull_policy" property for a service:

version: '3.7'

services:
  my-service:
    image: someimage/somewhere
    pull_policy: always

The docker-compose spec says:

pull_policy defines the decisions Compose implementations will make when it starts to pull images.

Possible values are (tl;dr, check spec for more details):

  • always: always pull
  • never: don't pull (breaks if the image can not be found)
  • missing: pulls if the image is not cached
  • build: always build or rebuild
Seb
  • 433
  • 4
  • 6
  • 1
    Do you know what is the lowest version of docker that supports this? I tried it and it said it is invalid. – Neal Sep 07 '21 at 15:11
  • 1
    @Neal no, sorry. I couldn't find any information about that. – Seb Sep 08 '21 at 14:43
  • 2
    I do not think this is valid. The spec link is not from the official Docker repo and `pull_policy` has no effect in current **docker-compose v1.29.2** and file version **3.8**. Only the suggested `docker-compose pull` will actually pull the images even if they exist – mitsos1os Sep 29 '21 at 14:28
  • 1
    @mitsos1os I believe you are correct. Thanks for the information. I will update the entry above now. In the source code for [1.29.2](https://github.com/docker/compose/blob/5becea4ca9f68875334c92f191a13482bcd6e5cf/compose/config/config.py#L65) you can see that the "pull_policy" key is missing and has thus no effect, even if it is available in the spec and thus passes validation. – Seb Sep 30 '21 at 08:50
  • 1
    "The spec link is not from the official Docker repo". Yes it is. In https://docs.docker.com/compose/compose-file/, the first paragraph says "Docker Compose 1.27.0+ implements the format defined by the Compose Specification." The Compose Specification is https://compose-spec.io/ whose GitHub repo this answer is linking to. – Emerson Farrugia Oct 14 '21 at 08:07
  • @EmersonFarrugia yes, the answer has not been wrong concerning the link between docker and the spec, but the spec is not fully implemented by docker compose. It is only "compatible" in terms of file format, but not functionally complete. – Seb Oct 15 '21 at 08:37
  • I was quoting from and referring to @mitsos1os comment, not the answer. – Emerson Farrugia Oct 16 '21 at 10:12
  • Maybe then according to https://github.com/compose-spec/compose-spec/blob/master/spec.md#version-top-level-element, `version` should not be used so that docker-compose understands it should implement Compose specification and not 3.7 where it is not present? – mitsos1os Oct 18 '21 at 09:28
  • Actually, I tried removing the `version` tag and still `docker-compose` didn't respect the `pull_policy` tag – mitsos1os Oct 18 '21 at 11:29
  • In the first line under "Version top-level element" it states that `Top-level version property is defined by the specification for backward compatibility but is only informative.` – Seb Oct 18 '21 at 13:50
  • 2
    'pull_policy: always' forces a pull of the image even if the local image is up to date. It works but is probably not the desired behavior in most cases. – yolabingo Mar 17 '22 at 17:48
  • @yolabingo I think it's OK. It will fetch *some* data (not sure how much) but it will quickly identify that the image is identical to a local one. So it's not the same thing as fetching the whole thing. – Pär Berge Aug 16 '23 at 13:11
25

To close this question, what seemed to have worked is indeed running

docker-compose stop
docker-compose rm -f
docker-compose -f docker-compose.yml up -d

I.e. remove the containers before running up again.

What one needs to keep in mind when doing it like this is that data volume containers are removed as well if you just run rm -f. In order to prevent that I specify explicitly each container to remove:

docker-compose rm -f application nginx php

As I said in my question, I don't know if this is the correct process. But this seems to work for our use case, so until we find a better solution we'll roll with this one.

Jens Wegar
  • 4,147
  • 4
  • 29
  • 34
  • What if you want to rollback to the previous container version? Rinse, repeat? – EightyEight Dec 09 '16 at 05:01
  • 1
    Have not tried it but yes, I assume as much. Since the container version should be defined in the docker-compose.yml (e.g. myimage:2.0.1) if you want to roll back you'd update the docker-compose.yml to the version you want to roll back to (e.g. 2.0.0) and the do the same rinse repeat process again. – Jens Wegar Dec 09 '16 at 08:53
  • if i want to roll back i just revert commit, let docker hub build and then wait for the updater to pick it up. probably not the most elaborate system but it works for my spare-time projects. – stephanlindauer Aug 28 '17 at 20:36
  • Remove everything doesn't seems like a solution but more like a dodgy one. – PierrickM Nov 17 '20 at 13:27
  • The `-f` flag is **optional** if the file is already called `docker-compose.yml`. – Kalaschni Apr 06 '22 at 07:57
11

Pull new Image: docker-compose pull

Rebuild docker container with new Image: docker-compose up --force-recreate --build -d

Delete unused Images: docker image prune -f

tiib
  • 111
  • 1
  • 3
  • Depending on your config and compose version this might not fetch the latest image from the registry if a local version of it already exists: https://docs.docker.com/compose/compose-file/05-services/#pull_policy Default is `pull_policy: missing`. It will only fetch the image if it's not in the `platform cache`. I'm not 100% sure what that is, but my guess is that it won't pull `my-registry/foo:latest` if the image `my-registry/foo:latest` is already present locally – Pär Berge Aug 16 '23 at 12:55
6

Option down resolve this problem

I run my compose file:

docker-compose -f docker/docker-compose.yml up -d

then I delete all with down --rmi all

docker-compose -f docker/docker-compose.yml down --rmi all

Stops containers and removes containers, networks, volumes, and images
created by `up`.

By default, the only things removed are:

- Containers for services defined in the Compose file
- Networks defined in the `networks` section of the Compose file
- The default network, if one is used

Networks and volumes defined as `external` are never removed.

Usage: down [options]

Options:
    --rmi type          Remove images. Type must be one of:
                        'all': Remove all images used by any service.
                        'local': Remove only images that don't have a custom tag
                        set by the `image` field.
    -v, --volumes       Remove named volumes declared in the `volumes` section
                        of the Compose file and anonymous volumes
                        attached to containers.
    --remove-orphans    Remove containers for services not defined in the
                        Compose file
Slavik Muz
  • 1,157
  • 1
  • 15
  • 28
4
docker-compose pull
docker-compose up -d
docker image prune -af

It works for me.

Pull the newest image first, Than update the container, Finally clean images that we don't need.

Yi-Ju Wu
  • 41
  • 1
  • I wish I have written on your answer first. Seems like you answered the same thing before this post: https://stackoverflow.com/a/71322296/7262144. `pull` depending on your compose and config might not actually fetch the latest version. – Pär Berge Aug 16 '23 at 13:05
3

I spent half a day with this problem. The reason was that be sure to check where the volume was recorded.

volumes: - api-data:/src/patterns

But the fact is that in this place was the code that we changed. But when updating the docker, the code did not change.

Therefore, if you are checking someone else's code and for some reason you are not updating, check this.

And so in general this approach works:

docker-compose down

docker-compose build

docker-compose up -d

3

A bit late, but at least with:
Docker version 20.10.17
Docker Compose version 2.9.0

You can use docker-compose up --pull=always -d

From CLI help:

--pull string Pull image before running ("always"|"missing"|"never") (default "missing")

developer10214
  • 1,128
  • 1
  • 11
  • 24
  • it does not works for me, there is no uch option for up https://docs.docker.com.xy2401.com/compose/reference/up/ but is for build https://docs.docker.com.xy2401.com/compose/reference/build/ – Daniel Feb 27 '23 at 21:00
  • Instead of using the CLI I would recommend putting it in the compose file according to: https://docs.docker.com/compose/compose-file/05-services/#pull_policy e.g add `pull_policy: always` under the service you want to configure – Pär Berge Aug 16 '23 at 12:46
1

I've seen this occur in our 7-8 docker production system. Another solution that worked for me in production was to run

docker-compose down
docker-compose up -d

this removes the containers and seems to make 'up' create new ones from the latest image.

This doesn't yet solve my dream of down+up per EACH changed container (serially, less down time), but it works to force 'up' to update the containers.

Dani K
  • 280
  • 1
  • 9
  • `docker-compose down` afaik also removes any data volume containers linked to the running containers. So no problem if the data volumes only contain stuff that can be re-created from a running container. But you should be careful if the volumes contain data you want to keep. – Jens Wegar Dec 01 '16 at 08:19
  • 3
    `down` removes, by default and current doc: containers, networks and default networks. Doc says 'Networks and volumes defined as external are never removed'. Works for me with named volumes (and I guess that's true for named networks as well). – arminfro Jul 20 '19 at 20:08
1

If the docker compose configuration is in a file, simply run:

docker-compose -f appName.yml down && docker-compose -f appName.yml pull && docker-compose -f appName.yml up -d
njeru
  • 49
  • 6
0

But

https://docs.docker.com/compose/reference/up/ -quiet-pull Pull without printing progress information

docker-compose up --quiet-pull

not work ?

BruceOverflow
  • 556
  • 9
  • 25
0

Your docker-compose.yml uses image to refer to ourprivate.docker.reg:5000/ourcompany/buildchaintest:0.1.8-dev. That means that running docker-compose build doesn’t take any action in regards to ourprivate.docker.reg:5000/ourcompany/buildchaintest:0.1.8-dev. There must be commands like the following run somewhere:

docker build -t ourprivate.docker.reg:5000/ourcompany/buildchaintest:0.1.8-dev
docker push ourprivate.docker.reg:5000/ourcompany/buildchaintest:0.1.8-dev

This would put the versioned build into your repository. But it would not update its latest tag. That would still point to the prior version (e.g., 0.1.7-dev).

Then, you ran the other commands on your jenkins:

cd $WORKSPACE && PROJECT_VERSION=$(cat VERSION)-dev
/usr/local/bin/docker-compose rm -f
/usr/local/bin/docker-compose build
docker tag ourprivate.docker.reg:5000/ourcompany/buildchaintest ourprivate.docker.reg:5000/ourcompany/buildchaintest:$PROJECT_VERSION
docker push ourprivate.docker.reg:5000/ourcompany/buildchaintest

As part of docker-compose build, you are effectively running docker pull ourprivate.docker.reg:5000/ourcompany/buildchaintest:0.1.8-dev on your server. However, that does not account for how the tag ourprivate.docker.reg:5000/ourcompany/buildchaintest:latest (which you refer to in the command docker tag ourprivate.docker.reg:5000/ourcompany/buildchaintest ourprivate.docker.reg:5000/ourcompany/buildchaintest:$PROJECT_VERSION) got onto your server. If the latest tag was not defined by something else beforehand, that docker tag command would give this error: No such image: ourprivate.docker.reg:5000/ourcompany/buildchaintest:latest. So, prior to running the commands you showed, your jenkins server must have run something like the following:

docker pull ourprivate.docker.reg:5000/ourcompany/buildchaintest

This command would cause it to pull whatever is set to latest at that time in your repository. Because you gave no proof that you ever pushed your newly build buildchaintest:0.1.8-dev as buildchaintest:latest prior to running the above docker pull command, we have to assume that this is where the old version comes from. As a result, your tag command effectively does this:

docker tag ourprivate.docker.reg:5000/ourcompany/buildchaintest:latest ourprivate.docker.reg:5000/ourcompany/buildchaintest:0.1.8-dev
docker push ourprivate.docker.reg:5000/ourcompany/buildchaintest:0.1.8-dev

Which, if latest is pointing to the same thing at 0.1.7-dev, is the same as doing:

docker tag ourprivate.docker.reg:5000/ourcompany/buildchaintest:0.1.7-dev ourprivate.docker.reg:5000/ourcompany/buildchaintest:0.1.8-dev
docker push ourprivate.docker.reg:5000/ourcompany/buildchaintest:0.1.8-dev

Then, later, when you run docker-compose pull && docker-compose up -d, of course it will pull what is set in the repository as ourprivate.docker.reg:5000/ourcompany/buildchaintest:0.1.8-dev which should be the old version because you tagged 0.1.7-dev as 0.1.8-dev.

Notes

You seem to be assuming that docker-compose build does something related to building buildchaintest. However, it does not. You set image but not build in your docker-compose.yml. That means docker-compose build will not build the buildchaintest docker image—it will just directly pull and run the docker image tag. Since docker-compose build doesn’t attempt to build buildchaintest, there’s no point to trying to tag or push that image after invoking it.

Also, docker-compose push exists and would do all of the tagging and pushing of things if you specify both build and image (because then image is used to inform docker-compose that it should set a tag for the built thing). This would push the correct tags (and would correctly be a no-op for your docker-compose.yml file).

Your docker-compose has build in it without image. Those things will be built wherever you run docker-compose up. So there is no point (unless you add image to set tags and save those built images and use docker-compose push) in running docker-compose build on the build server (beyond testing that building runs to completion). You’re not saving yourself any time or reducing the work performed by servers during deployment. You’re increasing the number of times things are built and the variability between nodes in your system (as whatever is built on your build server will be different (e.g., file timestamps, updated image tags) than whatever is running on your server.

Unfortunately, your question is not trustworthy. You use commands as if they have different behaviors than they are supposed to have. I am sorry to attack your question, but I have learned some surprising (to me) things about how docker tag and docker-compose work as a result. Thanks!

tl;dr

Make sure that you actually tag and push the correct image into your repository!

binki
  • 7,754
  • 5
  • 64
  • 110
0

You can also use docker-compose build without cache :

$ docker-compose build --no-cache && docker-compose up -d
  • That won't impact the service called `application` in the authors compose file. That service is using an image from the registry. Building with no cache will only make the whole thing slower and not solve the actual problem. – Pär Berge Aug 16 '23 at 12:43
-1

The docker-compose documentation for the 'up' command clearly states that it updates the container should the image be changed since the last 'up' was performed:

If there are existing containers for a service, and the service’s configuration or image was changed after the container’s creation, docker-compose up picks up the changes by stopping and recreating the containers (preserving mounted volumes).

So by using 'stop' followed by 'pull' and then 'up' this should therefore avoid issues of lost volumes for the running containers, except of course, for containers whose images have been updated.

I am currently experimenting with this process and will include my results in this comment shortly.

Paul Pritchard
  • 614
  • 2
  • 11
  • 23
-3

I am using following command to get latest images

sudo docker-compose down -rmi all

sudo docker-compose up -d