I often run into an issue with some our docker container applications that the simple fix is to restart the docker container. Unfortunately this is a manual process, and we have broken functionality until we discover which container is problematic and needs to be rebooted. This has me wondering if there is a good technique for auto restarting docker containers in certain situations?
Right now I'm thinking of a combination of the --autorestart flag, along with forcing the application to close when it encounters a known-issue. However, I'm not sure if this is the best approach.
If you're application is able to detect issues, you can easily have the container restart itself. The two important things are the --restart flag and that the application exists when it detects an issue.
Start the container in the background (-d) and set a restart policy:
docker run --restart unless-stopped -d [IMAGE] [COMMAND]
With the restart policy, you control what Docker does when the command exists. Using --restart unless-stopped tells Docker to always restart the command, no matter what the exit code of the command was. This way, you can have your application check its health, and if necessary use exit(1) or something similar to shutdown. When that happens, Docker will follow its restart policy and start a new container.
Although Docker doesn't really care about the return code, I would make sure that the application exists with a status code other than 0 to indicate an issue. This might be useful later if you do want to analyze logs or use your container from scripts.
Edit:
I initially used --restart always in the answer, but after some consideration I think it might be better to use --restart unless-stopped here. Its behavior is more predictable, because docker stop does actually stop a service. With --restart always, docker stop will stop the container, but then start a new one again, which isn't necessarily what you want or expect to happen.
Other than --restart=always and --restart=unless-stopped we also have --restart=on-failure[:max-retry] (Docker attempts to restarts the container if the container returns a non-zero exit code. You can optionally specify the maximum number of times that Docker will try to restart the container).
And we can also use Docker HEALTHCHECK instruction:
It tells Docker how to test a container to check that it is still working. This can detect cases such as a web server that is stuck in an infinite loop and unable to handle new connections, even though the server process is still running. We can also restart containers using Healthcheck.
[https://docs.docker.com/engine/reference/builder/#healthcheck][1]
Following are some examples that i have used to restart container and healing:
docker run -d \
--name autoheal \
--health-cmd='stat /etc/nginx/nginx.conf \
--health-interval=2s \
--restart=always \
-e AUTOHEAL_CONTAINER_LABEL=all \
-e DOCKER_SOCK=/var/run/docker.sock \
-e CURL_TIMEOUT=15 \
-v /var/run/docker.sock:/var/run/docker.sock \
willfarrell/autoheal
docker run -d \
--name autoheal \
--restart=always \
-e autoheal=true \
-e AUTOHEAL_DEFAULT_STOP_TIMEOUT=10 \
-e AUTOHEAL_INTERVAL=5 \
-e AUTOHEAL_START_PERIOD=0 \
-p 8080:8080 testing:latest
docker run -d --health-cmd='curl -sS http://localhost:80 || exit 1' \
--health-timeout=10s \
--health-retries=3 \
--health-interval=5s \
-p 8080:9080 testing:latest
You can use next command to restart container:
docker restart $container
Related
I'm new to Docker and came across this confusing (to me) command in one of the Docker online manuals (https://docs.docker.com/storage/bind-mounts/):
$ docker run -d \
-it \
--name devtest \
--mount type=bind,source="$(pwd)"/target,target=/app,readonly \
nginx:latest
What I found confusing was the use of both the -it flag and the -d flag. I thought -d means to run the container in the background, but -it means to allow the user to interact with the container via the current shell. What does it mean that both flags are present? What am I not understanding here?
The -i and -t flags influence how stdin and stdout are connected, even in the presence of the -d flag. Furthermore, you can always attach to a container in the future using the docker attach command.
Consider: If I try to start an interactive shell without passing -i...
$ docker run -d --name demo alpine sh
...the container will exit immediately, because stdin is closed. If I want to run that detached, I need:
$ docker run -itd --name demo alpine sh
This allows me to attach to the container in the future and interact with the shell:
$ docker attach demo
/ #
I'm following this guide to install docker for my GitLab server running on Ubuntu 16.4.
When I execute the following command:
docker run -d --name gitlab-runner --restart always \
-v /srv/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:latest
So far so good. However, when I run the next command to register the runner from this guide:
docker run --rm -t -i -v /srv/gitlab-runner/config:/etc/gitlab-runner --name gitlab-runner gitlab/gitlab-runner register
I keep getting the message:
docker: Error response from daemon: Conflict. The container name "/gitlab-runner" is already in use by container "b055ded012f9d0ed085fe84756604464afbb11871b432a21300064333e34cb1d". You have to remove (or rename) that container to be able to reuse that name.
However, when I run docker container list to see the list of containers, it's empty.
Anyone know how I can fix this error?
Just to add my 2-cents as I've also recently been through those GitLab documents to get the Docker GitLab runner working.
Following the Docker image installation and configuration guide, it tells you to start that container, however that I believe, is a mistake, and you want to do that after registering the Runner.
If you did run:
docker run -d --name gitlab-runner --restart always \
-v /srv/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:latest
Just remove the docker container with docker rm -f gitlab-runner, and move on to registering the runner.
docker run --rm -t -i -v /srv/gitlab-runner/config:/etc/gitlab-runner --name gitlab-runner gitlab/gitlab-runner register
This would register the runner, and also place the configuration in /srv/gitlab-runner/config/config.toml on the local machine.
You can then run the original docker run:
docker run -d --name gitlab-runner --restart always \
-v /srv/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:latest
(NB, if this doesn't work because of the name being in use again - just run the docker rm -f gitlab-runner command again - you won't lose the gitlab-runner configuration).
And that would stand up the Docker gitlab-runner with the configuration set from the register command.
Hope this helps!
You're trying to run two containers with the same name? Where did these instructions come from? Then in your response you're saying you get the error 'No such container: gitlab-runner-config' but that's not the name of any of the containers you're trying to run?
Seems that your first container is meant to be called gitlab-runner-config based on everything else I see in there, including your volumes-from. Probably that's why gitlab-runner doesn't show up in docker ps, because you're trying to get volumes from a container that doesn't exist. Try clearing everything, and then run the following:
$ docker run -d --name gitlab-runner-config --restart always \
-v /srv/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:latest
...
$ docker run -d --name gitlab-runner --restart always \
-v /var/run/docker.sock:/var/run/docker.sock \
--volumes-from gitlab-runner-config \
gitlab/gitlab-runner:latest
EDIT: OK so I read the guide, you're following the instructions wrong. It's saying in step 2, either do the one command, or the two afterwards. Either do a combined config and run container (which is called gitlab-runner) or do a config container (called gitlab-runner-config) then a runner container (called gitlab-runner). You're doing multiple steps with the same container name but mixing them up.
Run docker ps -a and you will see all your containers (even the not running ones), if you use the --rm option on run your container will be removed when stopped if that is the behaviour you are after.
You could always just skip the whole --name option if you want to create more than one of the same image and don't care about the name.
I also came across this, and opened an issue against the GitLab documentation. Here's my comment in there:
Actually, I think the issue might be something different:
On step 3, clicking on the link takes you to https://docs.gitlab.com/runner/register/index.html#docker.
In doing this, you land on the right section, near the end of the page. But this also means that you miss one important bit of information at the top of the page:
Before registering a Runner, you need to first:
Install it on a server separate than where GitLab is installed on
Obtain a token for a shared or specific Runner via GitLab's interface
That is, the documentation instructions recommend and assume that the gitlab runner container is on another machine. Thus they are not expected to work for containers on the same one.
My suggestion would be to add a note after the register step to check the registration requirements at the top of the page first.
Other than that, #johnharris85's answer would work for registering the runner on the same machine. The only extra thing you'd need to do is to add the --network="host" option to the command to do the registration. That is:
sudo docker run --rm -t -i \
-v /srv/gitlab-runner/config:/etc/gitlab-runner \
--network="host" --name gitlab-runner-register \
gitlab/gitlab-runner register
I start a docker container like this:
docker run -ti --restart="always" --name "lizmap" -p 80:80 -d -t \
-v /home/lizmap_project:/home \
-v /home/lizmap_var:/var/www/websig/lizmap/var \
-v /home/lizmap_tmp:/tmp \
jancelin/docker-lizmap
which makes the GIS server works like charm.
After the first two reboots the container comes up by self as expected. After some several reboots it keeps on telling me that it is restarting and restarting and restarting.
Logs are
apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
httpd (pid 7) already running
The workaround I do is to docker stop lizmap and docker rm lizmap and then start the container again with the code above.
Does anyone has an idea about how to avoid this workaround and make the container's restart working not only for the first two time.
The docker files come from this
Github
docker run \
-d \
-e "SOME_ENV_VAR=someValue" \
-h some.host.com \
--link db-thing:db \
--name someName \
-p 5555:5555 \
--restart always \
-v /someFile:/otherFile:ro \
-v /someDir/:/otherDir/ \
web-thing
I'm using docker 1.7.1 on CentOS. I started some containers with --restart always, then rebooted the server. Docker came back up, but none of the containers/images restarted. I thought they might depend on each other, so restarted the db-thing image, but even then the others still didn't restart. What could keep the containers from restarting?
Does this have anything to do with this: How to setup linkage between docker containers so that restarting won't break it?
I tried again and it worked. Doh! My best guess is that I was developing my docker commands in a file (to check into source control) and I must have forgotten to run the version of the command that had --restart always. Embarrassing!
I ran a Docker container using a very (8 lines) long list of arguments:
docker run -d -p 5000:5000 --restart=always --name registry \
-v `pwd`/auth:/auth \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
-v `pwd`/certs:/certs \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/registry.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/registry.key \
registry:2
I confirmed this was running via docker ps:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ff9c654bfc39 registry:2 "/bin/registry /etc/d" 2 days ago Up 13 minutes 0.0.0.0:5000->5000/tcp registry
I then stopped this container via docker stop ff9c654bfc39. I then tried re-running the container by issuing the exact same docker run ... (8 liner) as I did the first time:
Error response from daemon: Conflict. The name "registry" is already in use by container ff9c654bfc39. You have to delete (or rename) that container to be able to reuse that name.
So then I just tried docker restart ff9c654bfc39 and that seemed to work, but I'm not 100% sure Docker "remembered" my 8 lines of arguments from when I initially ran the container. Any ideas as to whether it is remembering? If not, what's the proper restart command to include those 8 lines?
As #gabowsky is explaining in the comments, yes, Docker will remember.
Using start, stop and restart will NOT destroy the container, hence remembering everything, including data (even between reboot of the host).
What stop does is to stop the process running inside the container. That's all.
Also, Docker store all the context, variables, etc... in an internal format. You don't have to specify command line arguments again.
To see what Docker knows about your container, you can run docker inspect.
On the contrary, rm will destroy everything, including none persisted data, and the container would need to be recreated again (Giving the arguments again this time).
As a final note, you should very much use names instead of SHA1 when referring containers in command line