85

I enjoy a lot using docker-compose.

Eg. on my server, when I want to update my app with minor changes, I only need to git pull origin master && docker-compose restart, works perfectly.

But sometimes, I need to rebuild (eg. I added an npm dependency, need to run npm install again).

In this case, I do docker-compose build --no-cache && docker-compose restart.

I would expect this to :

  • create a new instance of my container
  • stop the existing container (after the newer has finished building)
  • start the new one
  • optionally remove the old one, but this could be done manually

But in practice it seems to restart the former one again.

Is it the expected behavior?

How can I handle a rebuild and start the new one after it is built?

Maybe I missed a specific command? Or would it make sense to have it?

Bengi Besçeli
  • 3,638
  • 12
  • 53
  • 87
Augustin Riedinger
  • 20,909
  • 29
  • 133
  • 206
  • Others have already hit on the correct answer here. This answer to a similar question may also help: http://stackoverflow.com/a/39501539/596285 – BMitch Mar 12 '17 at 20:42

9 Answers9

57

from the manual docker-compose restart

If you make changes to your docker-compose.yml configuration these changes will not be reflected after running this command.

you should be able to do

$docker-compose up -d --no-deps --build <service_name>

The --no-deps will not start linked services.

denov
  • 11,180
  • 2
  • 27
  • 43
  • 8
    Each time I use your answer, the *`--no-deps` will not start linked services* scares me. Could you be more specific on what this means/implies? – Augustin Riedinger Mar 01 '18 at 10:40
  • 3
    that's a good question, you should ask it... in short - Service links create environment variables which allow containers to communicate with each other within a stack, or with other services outside of a stack. You can specify service links explicitly when you create a new service or edit an existing one, or specify them in the stackfile for a service stack. BUT you really should use network in your compose file. – denov Mar 01 '18 at 18:30
  • Looks like service_name is optional and it will just rebuild all your services if left off. – James Harrington Aug 31 '18 at 19:00
  • `docker-compose up -d --no-deps --build # [servicename]` – Wes Turner Sep 24 '22 at 20:14
  • This can't be correct, as docker must remove and then replace said container, resulting in downtime (however short, still downtime). – fullStackChris May 17 '23 at 06:55
  • I've confirmed my hunch with a reproducable example, be careful with this answer if your container is exposed at a port and you expect truly constant uptime. With this answer there WILL be a short 1-5 second window in which any pings to that container's exposed port will fail. – fullStackChris May 17 '23 at 08:21
55

The problem is that restart will restart your current containers, which is not what you want.

As an example, I just did this

  • change the docker file for one of the images
  • call docker-compose build to build the images
  • call docker-compose down1 and docker-compose up
    • docker-compose restart will NOT work here
    • using docker-compose start instead also does not work

To be honest, i'm not completly sure you need to do a down first, but that should be easy to check.1 The bottomline is that you need to call up. You will see the containers of unchanged images restarting, but for the changed image you'll see recreating.

The advantage of this over just calling up --build is that you can see the building-process first before you restart.

1: from the comments; down is not needed, you can just call up --build. Down has some "down"-sides, including possible being destructive to your (volume-)data.

Nanne
  • 64,065
  • 16
  • 119
  • 163
  • 20
    `docker-compose down` is not required, `up` will detect the build has been updated and recreate the containers. Also as the other answers have noted op will probably need `docker-compose up -d` – Matt Mar 12 '17 at 11:22
  • 9
    Actually I should say `down` is a _bad_ idea. It destroys everything, which could include volume data in some setups. – Matt Mar 12 '17 at 11:24
  • 1
    you should not have data in a container anyway, if it is not a data container that is, but the point is valid. – Nanne Mar 12 '17 at 18:50
  • 2
    Local [volumes](https://docs.docker.com/engine/tutorials/dockervolumes/#data-volumes), either defined in compose or autogenerated by a Dockerfile, will be destroyed by a down. – Matt Mar 12 '17 at 23:09
  • @Matt to keep the argument (which is a good one btw) clear I have added it a bit more clearly in the edit / disclaimer – Nanne Mar 13 '17 at 07:42
  • I'll go for the `docker-compose up -d --build` but can I use it with a `--no-cache` option as well? – Augustin Riedinger Sep 29 '17 at 14:46
48

Use the --build flag to the up command, along with the -d flag to run your containers in the background:

docker-compose up -d --build

This will rebuild all images defined in your compose file, then restart any containers whose images have changed.

-d assumes that you don't want to keep everything running in your shell foreground. This makes it act more like restart, but it's not required.

jkinkead
  • 4,101
  • 21
  • 33
14

Don't manage your application environment directly. Use deployment tool like Rancher / Kubernetes. Using one you will be able to upgrade your dockerized application without any downtime and even downgrade it should you need to.

Running Rancher is as easy as running another docker container as this tool is available in the Docker Hub.

Mike Doe
  • 16,349
  • 11
  • 65
  • 88
9

You can use Swarm. Init swarm first by docker swarm init command and use healthcheck in docker-compose.yml.

Then run below command:

docker stack deploy -c docker-compose.yml project_name

instead of

docker-compose up -d.

When docker-compose.yml file is updated only run this command again:

docker stack deploy -c docker-compose.yml project_name

Docker Swarm will create new version of services and stop old version after that.

Hossein
  • 3,755
  • 2
  • 29
  • 39
  • 1
    Thanks for this. I did started to use swarm, it is a decent solution though it is still harder to get started with than compose. Few things are missing (`docker stack logs`, using compose file by default to avoid writing it in commands etc.). IMHO it is a pity that compose doesn't include rolling updates by default, as this is the feature users lack the most. – Augustin Riedinger Jan 27 '20 at 09:12
  • 2
    Or for the last command, we could update the specific service by `docker service update --force drnext_back_server`. – M. Rostami Mar 12 '21 at 23:46
6

Though the accepted answer shall work to rebuild the container before starting the new one as a replacement, it is ok for simple use case, but the container will still be down during new container initialization process. If this is quite long, it can be an issue.

I managed to achieve rolling updates with docker-compose (along with a nginx reverse proxy), and detailed how I built that in this github issue: https://github.com/docker/compose/issues/1786#issuecomment-579794865

Hope it can help!

Augustin Riedinger
  • 20,909
  • 29
  • 133
  • 206
3

Run the following commands:

docker-compose pull

docker-compose up -d --no-deps --build <service_name>

As the top rated answer mentioned

docker-compose up -d --no-deps --build <service_name>

will restart a single service without taking down the whole compose.

I just wanted to add to the top answer in case anyone is unsure how to update an image without restarting the container.

linktoahref
  • 7,812
  • 3
  • 29
  • 51
2

Another way:

docker-compose restart in your case could be replaced with docker-compose up -d --force-recreate, see https://docs.docker.com/compose/reference/up/

0

Running docker-compose up while docker-compose is in the running state, will recreate container that got their configuration changed.

Thats the easiest way, and it will only affect containers that got their configuration changed.

root@docker:~# docker-compose up
traefik is up-to-date
nginx is up-to-date
Recreating php ... done
disco_stu
  • 1
  • 1