575

I have a docker-compose.yml file that contains 4 containers: redis, postgres, api and worker.

During the development of the worker container, I often need to restart it in order to apply changes. Is there any good way to restart a single container (e.g. worker) without restarting the others?

mit
  • 11,083
  • 11
  • 50
  • 74
Bryan Chen
  • 45,816
  • 18
  • 112
  • 143

11 Answers11

664

It is very simple: Use the command:

docker-compose restart worker

You can set the time to wait for stop before killing the container (in seconds)

docker-compose restart -t 30 worker

Note that this will restart the container but without rebuilding it. If you want to apply your changes and then restart, take a look at the other answers.

Philipp Claßen
  • 41,306
  • 31
  • 146
  • 239
bmkrio
  • 6,860
  • 1
  • 11
  • 3
  • 3
    for me it worked, but a general question if allowed here: does 'restart' take care of linked containers and update the /etc/hosts or doesn't a 'restart' change any IPs at all? – michabbb Jan 11 '16 at 17:04
  • 2
    The containers are linked by name and typically the only IP you need to worry about is the external docker host IP (typically 192.168.99.100). Where there can be some trouble is if you, say, restart a database container that other containers are connected to. The dependent containers will have to be resilient enough to reconnect. – Ryan Kimber Apr 02 '16 at 16:34
  • 68
    The OP states that he needs to "restart it in order to apply changes". According to the docs the `docker-compose restart` commands will NOT apply any changes. "If you make changes to your `docker-compose.yml` configuration these changes are not reflected after running this command." Therefore use `docker-compose up -d --build`. https://docs.docker.com/compose/reference/restart/ – featherbelly Mar 06 '18 at 13:39
  • 12
    nb, *worker* is the name given to the service in the yaml file and not anything that you see when running `docker ps -a` – worc Oct 31 '18 at 18:10
  • 6
    This other answer is much better https://stackoverflow.com/a/39501539/292408, as `restart` doesn't apply changes even if you already ran a `docker-compose build `and this is a non-working/incorrect answer. – Elijah Lynn Feb 07 '19 at 19:17
  • I edited it now to mention the fact that the rebuilding step is missing. – Philipp Claßen May 16 '19 at 18:04
  • In case you need to restart using a prefix for your app `docker-compose -p myapp restart worker` – phi Jul 02 '21 at 07:56
  • There is a misunderstanding here about what needs to be restarted. If it is just some change in the code that is stored in the container, then this command helps. If it is about changes in the Dockerfile that builds the image on which the container is running, then this command does not help. Most of the time in coding projects, you will not want to change the image, but the code that you run inside the container, and then this command is enough. – questionto42 Sep 06 '22 at 22:33
283

The other answers to restarting a single node are on target, docker-compose restart worker. That will bounce that container, but not include any changes, even if you rebuilt it separately. You can manually stop, rm, create, and start, but there are much easier methods.

If you've updated your code, you can do the build and reload in a single step with:

docker-compose up --detach --build

That will first rebuild your images from any changed code, which is fast if there are no changes since the cache is reused. And then it only replaces the changed containers. If your downloaded images are stale, you can precede the above command with:

docker-compose pull

To download any changed images first (the containers won't be restarted until you run a command like the up above). Doing an initial stop is unnecessary.

And to only do this for a single service, follow the up or pull command with the services you want to specify, e.g.:

docker-compose up --detach --build worker

Here's a quick example of the first option, the Dockerfile is structured to keep the frequently changing parts of the code near the end. In fact the requirements are pulled in separately for the pip install since that file rarely changes. And since the nginx and redis containers were up-to-date, they weren't restarted. Total time for the entire process was under 6 seconds:

$ time docker-compose -f docker-compose.nginx-proxy.yml up --detach --build
Building counter
Step 1 : FROM python:2.7-alpine
 ---> fc479af56697
Step 2 : WORKDIR /app
 ---> Using cache
 ---> d04d0d6d98f1
Step 3 : ADD requirements.txt /app/requirements.txt
 ---> Using cache
 ---> 9c4e311f3f0c
Step 4 : RUN pip install -r requirements.txt
 ---> Using cache
 ---> 85b878795479
Step 5 : ADD . /app
 ---> 63e3d4e6b539
Removing intermediate container 9af53c35d8fe
Step 6 : EXPOSE 80
 ---> Running in a5b3d3f80cd4
 ---> 4ce3750610a9
Removing intermediate container a5b3d3f80cd4
Step 7 : CMD gunicorn app:app -b 0.0.0.0:80 --log-file - --access-logfile - --workers 4 --keep-alive 0
 ---> Running in 0d69957bda4c
 ---> d41ff1635cb7
Removing intermediate container 0d69957bda4c
Successfully built d41ff1635cb7
counter_nginx_1 is up-to-date
counter_redis_1 is up-to-date
Recreating counter_counter_1

real    0m5.959s
user    0m0.508s
sys     0m0.076s
Elijah Lynn
  • 12,272
  • 10
  • 61
  • 91
BMitch
  • 231,797
  • 42
  • 475
  • 450
  • This is interesting, but could it be used along with the `-no-cache` option? Say I added something into my `package.json` and need to re`RUN npm install` but the `Dockerfile` itself hasn't changed – Augustin Riedinger Sep 29 '17 at 14:42
  • 2
    @augustinriedinger If your input file is changed and you include that with a `COPY` command, that will break the cache automatically. – BMitch Sep 29 '17 at 14:46
  • I did not get the `COPY` part of your comment. Indeed, editing the `Dockerfile` would work, but this is a dirty hack, especially since the file is tracked in `git`... – Augustin Riedinger Sep 29 '17 at 15:36
  • @augustinriedinger there are too many unknowns in your scenario to try to clarify this in a comment. This would be better handled as a separate question. – BMitch Sep 29 '17 at 15:55
  • Well the question is [there](https://stackoverflow.com/questions/42529211/how-to-rebuild-and-update-a-container-without-downtime-with-docker-compose) and apparently you already linked there to this question :) – Augustin Riedinger Sep 29 '17 at 16:00
  • 1
    @augustinriedinger thanks. I'm mobile so I can't see the linked questions. From the steps in your question you should already have a `COPY` command in your Dockerfile. The `git pull` will update the package.json file and the build cache will break when docker sees you copy in a different file. – BMitch Sep 29 '17 at 16:16
  • 1
    Thanks did not know about this behavior! I was using `ADD` instead of `COPY` but apparently the latter is a [best practice](https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#add-or-copy) so I'll go for it! – Augustin Riedinger Sep 29 '17 at 21:24
  • 1
    @augustinriedinger `ADD` will have the same result as `COPY` on the cache bust, but (as suggested in the best practices link) most don't need the extra capabilities so I don't even bother mentioning it. – BMitch Sep 29 '17 at 21:27
  • ```docker-compose -p up -d --build ``` worked for me, thanks for the help. – user8675309 Feb 14 '19 at 18:54
  • From docs from exeture: `docker-compose help up`, `docker-compose up` command will pick up the changes by stopping an recreating the containers。 Just give `docker-compose help` a try. – chen Jacky Dec 28 '19 at 06:42
77

To restart a service with changes here are the steps that I performed:

docker-compose stop -t 1 worker
docker-compose build worker
docker-compose up --no-start worker
docker-compose start worker
rgov
  • 3,516
  • 1
  • 31
  • 51
Jeff
  • 1,122
  • 8
  • 7
  • 30
    If you need changes to apply with a build, you can easily do a `docker-compose up -d --build` and it will rebuild everything and restart any changed containers. No need for the stop first, with downtime, and separate create and start commands. – BMitch Sep 15 '16 at 00:05
  • 13
    Yes, if you want to restart all services, but the OP only wants to restart a single service and not restart the others – Jeff Sep 16 '16 at 16:49
  • 4
    See the answer I posted, in the example, the `up` will only recreated the container that had been changed and therefore needed a restart. – BMitch Sep 16 '16 at 17:26
  • 1
    @BMitch somehow it doesn't always work for Rust containers. Even though I don't change anything in the source code, doing `docker-compose up -d --build` will often re-compile the project. – Desprit May 26 '21 at 07:40
33

Following command

docker-compose restart worker

will just STOP and START the container. i.e without loading any changes from the docker-compose.xml

STOP is similar to hibernating in PC . Hence stop/start will not look for any changes made in configuration file . To reload from the recipe of container (docker-compose.xml) we need to remove and create the container (Similar analogy to rebooting the PC )

So commands will be as following

docker-compose stop worker       // go to hibernate
docker-compose rm worker        // shutdown the PC 
docker-compose create worker     // create the container from image and put it in hibernate

docker-compose start worker //bring container to life from hibernation
Mr Coder
  • 8,169
  • 5
  • 45
  • 74
  • 1
    +1, many thanks! For `rm` line option `-f` comes handy (no prompt) and with current docker `create` and `start` is merged as `up` (so in total we have 3 commands not 4), and for `up` option `-d` is useful (execution is in the background). – astrowalker Dec 26 '19 at 07:54
18

Since some of the other answers include info on rebuilding, and my use case also required a rebuild, I had a better solution (compared to those).

There's still a way to easily target just the one single worker container that both rebuilds + restarts it in a single line, albeit it's not actually a single command. The best solution for me was simply rebuild and restart:

docker-compose build worker && docker-compose restart worker

This accomplishes both major goals at once for me:

  1. Targets the single worker container
  2. Rebuilds and restarts it in a single line

Hope this helps anyone else getting here.

patricknelson
  • 977
  • 10
  • 16
16

Restart Service with docker-compose file

docker-compose -f [COMPOSE_FILE_NAME].yml restart [SERVICE_NAME]

Use Case #1: If the COMPOSE_FILE_NAME is docker-compose.yml and service is worker

docker-compose restart worker

Use Case #2: If the file name is sample.yml and service is worker

docker-compose -f sample.yml restart worker

By default docker-compose looks for the docker-compose.yml if we run the docker-compose command, else we have flag to give specific file name with -f [FILE_NAME].yml

Jinna Balu
  • 6,747
  • 38
  • 47
11

The answer's here are talking about the reflection of the change on the docker-compose.yml file.

But what if I want to incorporate the changes I have done in my code, and I believe that will be only possible by rebuilding the image and that I do with following commands

1. docker container stop

docker stop container-id

2. docker container removal

docker rm container-id

3. docker image removal

docker rmi image-id

4. compose the container again

docker-compose up container-name
Anshul Sharma
  • 1,018
  • 3
  • 17
  • 39
  • 2
    I think you should use the service key rather than container name `docker-compose up [service key]` – Maciek Rek Jul 11 '20 at 18:11
  • With container name it becomes easier as you can run it again by doing CTRL + R. – Anshul Sharma Aug 22 '20 at 03:35
  • i want to put this in Jenkins pipeline. So whenever there is a new code push, docker will build a new image. If there is no Container created already for the first time then docker stop container-id will throw error. How will you solve it? – Rafique Mohammed May 23 '22 at 08:13
  • @RafiqueMohammed, in case of Jenkins pipeline, i think you would not want to take risk of bringing down your service, so the steps you should follow are 1. Bring up your new containers, with a different tag so that it does not override existing containers, you can use commit-id as tag 2. redirect your traffic to new container 3. Bring down your old container – Anshul Sharma May 26 '22 at 13:23
10

Restart container

If you want to just restart your container:

docker-compose restart servicename

Think of this command as "just restart the container by its name", which is equivalent to docker restart command.

Note caveats:

  1. If you changed ENV variables they won't updated in container. You need to stop it and start again. Or, using single command docker-compose up will detect changes and recreate container.

  2. As many others mentioned, if you changed docker-compose.yml file itself, simple restart won't apply those changes.

  3. If you copy your code inside container at the build stage (in Dockerfile using ADD or COPY commands), every time the code changes you have to rebuild the container (docker-compose build).

Correlation to your code

docker-compose restart should work perfectly fine, if your code gets path mapped into the container by volume directive in docker-compose.yml like so:

services:

  servicename:
    volumes:
      - .:/code

But I'd recommend to use live code reloading, which is probably provided by your framework of choice in DEBUG mode (alternatively, you can search for auto-reload packages in your language of choice). Adding this should eliminate the need to restart container every time after your code changes, instead reloading the process inside.

Community
  • 1
  • 1
Lev Rubel
  • 183
  • 1
  • 9
6

Simple 'docker' command knows nothing about 'worker' container. Use command like this

docker-compose -f docker-compose.yml restart worker

Shtlzut
  • 2,174
  • 1
  • 16
  • 14
  • 5
    does not work -- new changes to the coker-compose.yml did not get applied on restart – jlee Sep 01 '16 at 22:44
4

To apply changes to a Docker Compose file while only restarting a single service, you can use the docker-compose command with the up command and specify the service name. For example:

$ docker-compose up -d --no-deps myservice

This command will update the configuration for the myservice service and restart it, without touching any of the other services in the Compose file. The -d flag runs the services in the background, and the --no-deps flag tells Compose not to start any dependencies of the myservice service.

Alternatively, you can use the restart command to restart a single service:

$ docker-compose restart myservice

This will apply the latest configuration for the myservice service and restart it.

Note that this command will not apply any changes to the Compose file itself, it will only restart the service using the current configuration.

Marc Sances
  • 2,402
  • 1
  • 19
  • 34
Bobby
  • 41
  • 2
1

After making changes, you need to pull the changes into the server and then reacreate the container. So as the documentation shows:

docker-compose pull worker && docker-compose up -d --no-deps worker

pull worker will make only this project to be pulled to the server, and --no-deps will prevent from restart containers the worker container depends on.

Huander Tironi
  • 329
  • 4
  • 7