How to restart a Docker service in global mode (non-replicated)? - docker

In Docker Swarm mode, how can I restart a single global service? Is it even possible? I know you can scale replicated services to zero then back to 1+, but there doesn't appear to be any documentation on how to have the same effect with global services.
I am updating my SSL certificate so would like to just restart our reverse proxy instead of restarting our entire app (via restarting the docker service).
The docs just mention you cannot scale global services:
The scale command enables you to scale one or more replicated services either up or down to the desired number of replicas. This command cannot be applied on services which are global mode.

You can force a rolling update of a service, either globally scheduled or replicated using docker service update --force ${service_name}. Here's an example compose file:
version: '3'
services:
busybox-global:
image: busybox
command: tail -f /dev/null
deploy:
mode: global
busybox-replicated:
image: busybox
command: tail -f /dev/null
deploy:
replicas: 2
Verify it has started:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
917aefdc910b busybox:latest "tail -f /dev/null" 50 seconds ago Up 31 seconds sched_busybox-global.q44zx0s2lvu1fdduk800e5ini.hzn6jnzh7x539timamphzzw8a
7187fbbde0da busybox:latest "tail -f /dev/null" About a minute ago Up 31 seconds sched_busybox-replicated.1.i4nm7lpr1spmf0aorh1dtcqrc
f04a0062b088 busybox:latest "tail -f /dev/null" About a minute ago Up 31 seconds sched_busybox-replicated.2.oc6zn0ziqg9wyzofokek8eb24
$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
gto0d5a6betb sched_busybox-global global 1/1 busybox:latest
yfq5mne0qhtj sched_busybox-replicated replicated 2/2 busybox:latest
$ docker service ps sched_busybox-global
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
hzn6jnzh7x53 sched_busybox-global.q44zx0s2lvu1fdduk800e5ini busybox:latest bmitch-asusr556l Running Running 49 seconds ago
Force the rolling update:
$ docker service update --force sched_busybox-global
sched_busybox-global
overall progress: 1 out of 1 tasks
q44zx0s2lvu1: running [==================================================>]
verify: Service converged
$ docker service ps sched_busybox-global
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
zcfocrfjvvux sched_busybox-global.q44zx0s2lvu1fdduk800e5ini busybox:latest bmitch-asusr556l Running Running 7 seconds ago
hzn6jnzh7x53 \_ sched_busybox-global.q44zx0s2lvu1fdduk800e5ini busybox:latest bmitch-asusr556l Shutdown Shutdown 10 seconds ago
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3c5fe0f79e3d busybox:latest "tail -f /dev/null" About a minute ago Up About a minute sched_busybox-global.q44zx0s2lvu1fdduk800e5ini.zcfocrfjvvuxz6tkge0pn0bq2
917aefdc910b busybox:latest "tail -f /dev/null" 3 minutes ago Exited (137) About a minute ago sched_busybox-global.q44zx0s2lvu1fdduk800e5ini.hzn6jnzh7x539timamphzzw8a
7187fbbde0da busybox:latest "tail -f /dev/null" 3 minutes ago Up 2 minutes sched_busybox-replicated.1.i4nm7lpr1spmf0aorh1dtcqrc
f04a0062b088 busybox:latest "tail -f /dev/null" 3 minutes ago Up 2 minutes sched_busybox-replicated.2.oc6zn0ziqg9wyzofokek8eb24
The same would have worked if I forced an update to the replicated service.

Related

What are the extra containers removed by "docker container prune" not listed by "docker ps -a"?

~/tmp/Counter1 ⌚ 10:18:24
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a46d397337e6 xx "echo ls" 20 hours ago Exited (0) 20 hours ago cranky_snyder
28d7339e57aa bf3a41a4ae8f "/bin/sh -c 'echo $e…" 21 hours ago Exited (0) 21 hours ago unruffled_archimedes
~/tmp/Counter1 ⌚ 10:18:27
$ docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
a46d397337e68101fe983f354f87e8b4c0e086a4157dce7e7c4a2558105da525
28d7339e57aa222697851aaf4fdd36da2cbbc16f5fa9d4373ac499f8f8e15de5
a3cf99470e2f6e623c97db14249fa14e0afe9fd01eaac1ef6087ef98575f3690
5123adaa9fab02346c589aa23d3dd1eae1085138ec0e9cb23f388bbc5d668a92
45727d359ea4a036dd466f72fbaa750b135244d730b514c63a96518c71b4ad90
3260c4155074df32038ee31273e7059c1755fe6145b98d187ca006e1a39c3636
7d9c83d179932b1c97d43077cfe19fb6bcac123e295affcfa4cc791c43ddf513
3e32ee26e2e91ffc704cb27069cddf8f2f576ca407b4d8969e528c5a229cd855
46e8782774e2a6d5c8885fa5710134e1cc26e4abd75f29d883e4b32abec07d82
4728995a0162a033869e9fdd306435b1365309da643b2bcfa708c04839e7993c
Total reclaimed space: 0B
If I repeat the same thing, I see the right number of docker container removed. But after some time of playing with more containers, I again see a similar mismatch in the number of containers.
If I understand correctly, docker ps -a should show me all containers. Wonder what the other SHAs are from?

Parallel code execution in Docker containers

I have a script that scrapes data by URLslist.
This script is executing in a docker container.
I would like to run it in multiple instances, for example, 20.
For that, I wanted to use docker-compose scale worker=20 and to pass the INDEX to each instance so that the script knows which URLs should be scraped .
Example.
ID, URL
0 https://example.org/sdga2
1 https://example.org/fsdh34
2 https://example.org/fs4h35
3 https://example.org/f1h36
4 https://example.org/fs4h37
...
If there are 3 instances, 1st instance of script should process a url whose ID equals to 0, 3, 6, 9 i.e. ID = INDEX + INSTANCES_NUM * k.
I don't know how to pass INDEX to script running in Docker container.
Of course, I can duplicate services in docker-compose.yml with different INDEX in environment vars. But if instances number is greater 10 or even 50 it will be a very bad solution)
Does anyone know how do this?
With docker-compose, I don't believe there's any support for this. However, with swarm mode, which can use a similar compose file, you can pass {{.Task.Slot}} as an environment variable using service templates. E.g.
version: '3'
services:
test:
image: busybox
command: /bin/sh -c "echo My task number is $$task_id && tail -f /dev/null"
environment:
task_id: "{{.Task.Slot}}"
deploy:
replicas: 5
Instead of docker-compose up, I deploy with docker stack deploy -c docker-compose.yml test. My local swarm cluster is just a single node created with docker swarm init.
Then, reviewing each of these running containers:
$ docker ps --filter label=com.docker.swarm.service.name=test_test
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ccd0dbebbcbe busybox:latest "/bin/sh -c 'echo My…" About a minute ago Up About a minute test_test.3.i3jg6qrg09wjmntq1q17690q4
bfaa22fa3342 busybox:latest "/bin/sh -c 'echo My…" About a minute ago Up About a minute test_test.5.iur5kg6o3hn5wpmudmbx3gvy1
a372c0ce39a2 busybox:latest "/bin/sh -c 'echo My…" About a minute ago Up About a minute test_test.4.rzmhyjnjk00qfs0ljpfyyjz73
0b47d19224f6 busybox:latest "/bin/sh -c 'echo My…" About a minute ago Up About a minute test_test.1.tm97lz6dqmhl80dam6bsuvc8j
c968cb5dbb5f busybox:latest "/bin/sh -c 'echo My…" About a minute ago Up About a minute test_test.2.757e8evknx745120ih5lmhk34
$ docker ps --filter label=com.docker.swarm.service.name=test_test -q | xargs -n 1 docker logs
My task number is 3
My task number is 5
My task number is 4
My task number is 1
My task number is 2
why don't you use a database? mysql or redis.
each container can fetch urls from the database and you can mark fetched urls as complete, always fetch not completed urls from each container. This can scale.

How to restart my Docker container?

This is what ps -a gives us
NAMES
4514ea1b7b22 debian "--name gallant_spen…" 9 minutes ago Created peaceful_engelbart
df9bd2731a2b debian "--name gallant_spen…" 9 minutes ago Created happy_hodgkin
dd5b1f1b39ec redis "docker-entrypoint.s…" 32 minutes ago Up 31 minutes 6379/tcp myred
ffd6ef9d8bd5 redis "docker-entrypoint.s…" 32 minutes ago Exited (127) 32 minutes ago festive_jennings
9d01d321adad redis "docker-entrypoint.s…" 33 minutes ago Exited (0) 32 minutes ago agitated_shannon
eb7c13e7cdee debian "ls /data" 2 days ago Exited (0) 9 seconds ago gallant_spence
8991a31b1e38 debian "ls /data" 2 days ago Exited (0) 2 days ago determined_minsky
I have tried in this manner
docker start `docker ps -q -l` gallant_spence
But error ocurrs
Error response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused "exec: \"--name\": executable file not found in $PATH": unknown
gallant_spence
Error: failed to start containers: 4514ea1b7b22
I am interested in data volume that has been mounted in my previous work on this container
"Mounts": [
{
"Type": "bind",
"Source": "/home/mm/code/lesson_04",
"Destination": "/data",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
If I try
mm#6830s:~$ docker start -ai gallant_spence
one_sample.py
parallel_series.py
Python files are added to data folder so I thought that it worked.Then I try again
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dd5b1f1b39ec redis "docker-entrypoint.s…" About an hour ago Up About an hour 6379/tcp myred
Hot to fix this?
You start a stopped container with
docker start [OPTIONS] CONTAINER [CONTAINER...]
For your case, you can use:
docker start gallant_spence or
docker start eb7c13e7cdee
As it is shown by the docker ps -a result, your container is configured with this CMD:
"ls /data"
This means that every time you start your container, this command will run and the container will then exit. This is how containers work. When their primary process finishes, they exit.
About the error you get and docker ps -q -l:
-q (from "quiet") tells the command to only print the container IDs
-l (from "last") tells the command to print the latest created container
This means that the above command brings you back: 4514ea1b7b22. If we put together all things...
your command:
docker start `docker ps -q -l` gallant_spence
turns to:
docker start 4514ea1b7b22 gallant_spence
The fail message you get is for 4514ea1b7b22 because it doesn't have a CMD set properly to start. I see something like: --name gallant_spen…

Ports not accessable

I installed docker and issues a 'docker swarm init' command.
I'm trying to launch a stack using the following command: docker stack deploy -c docker-compose.yml mystack
The docker-compose file can be found here, the first docker file here and the second here
The output of 'docker ps' is:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f582b3e8d33e tons/ip2country:latest "/bin/sh -c 'java -D…" 8 seconds ago Up 6 seconds 8080/tcp ip2flag_country-service.1.t5rvuqaw8tj7v20u0xo0dgy6x
bbf2c8304f1a tons/ip2flag:latest "/bin/sh -c 'java -D…" 10 seconds ago Up 8 seconds 8080/tcp ip2flag_app.1.z00gz8adj2yshpgimaw2o55d3
cbc7eaace4bf portainer/portainer "/portainer" 39 minutes ago Up 39 minutes 0.0.0.0:9000->9000/tcp portainer
The output of 'docker service ls' is:
ID NAME MODE REPLICAS IMAGE PORTS
ex51pyh1oyyo ip2flag_app replicated 1/1 tons/ip2flag:latest *:8080->8080/tcp
yhbt97lmjqan ip2flag_country-service replicated 1/1 tons/ip2country:latest
Since I'm running this on localhost I'd expect http://localhost:8080/ to return some sort of data. But it just times out. If I attach to the container and execute something like wget localhost:8080/some/path it works as expected. So the service is running and within the container listening to port 8080. However the port isn't exposed outside of dockers net. Further more I can add that launching with 'docker-compose up' works just fine too. But not with 'docker stack deploy'. Any clue about what I'm doing wrong?

Docker compose yml inheritance

There are two tasks: run app container, run almost the same deploy-app container. The differences for them, for example, that deploy container does not have port sharing.
So, I made configs for this tasks...
./dockerfiles/base.yml:
app:
net: docker_internal_net
environment:
APPLICATION_SERVER: "docker"
./dockerfiles/base.run.yml:
app:
container_name: project-app
# set the build context to the project root
build: ..
volumes:
- /var/log/project/nginx:/var/log/nginx
- /var/log/project/php-fpm:/var/log/php5-fpm
- ..:/var/www/project
./dockerfiles/dev/run.yml:
app:
dockerfile: ./dockerfiles/dev/run-app/Dockerfile
ports:
- "80:80"
- "22:22"
environment:
DEV_SSH_PUBKEY: "$SSH_PUBLIC_KEY"
APPLICATION_PLATFORM: "dev"
./dockerfiles/dev/build.yml:
app:
container_name: project-app-deploy
# set the build context to the project root
build: ../..
dockerfile: ./dockerfiles/dev/build-app/Dockerfile
environment:
APPLICATION_PLATFORM: "dev"
volumes:
- ../..:/var/www/project
So I can tun the app container like this:
$ docker-compose -f ./dockerfiles/base.yml -f ./dockerfiles/base.run.yml -f ./dockerfiles/dev/run.yml up -d app
Creating project-app
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dae45f3f2c42 dockerfiles_app "/sbin/my_init" 2 seconds ago Up 1 seconds 0.0.0.0:2223->22/tcp, 0.0.0.0:8081->80/tcp project-app
Everything okay. But if then I trying to run deploy-app container, I will receive this message:
$ docker-compose -f ./dockerfiles/base.yml -f ./dockerfiles/dev/build.yml up -d app
Recreating project-app
WARNING: Service "app" is using volume "/var/www/project" from the previous container. Host mapping ".." has no effect. Remove the existing containers (with `docker-compose rm app`) to use the host volume mapping.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
53059702c09b dockerfiles_app "/sbin/my_init" 6 seconds ago Up 4 seconds 22/tcp, 80/tcp project-app-deploy
This is because both of them are shared one local directory? But why I can run deploy-app container manually without docker-compose?
$ docker run -d --net docker_internal_net -e APPLICATION_SERVER=docker -e APPLICATION_PLATFORM=dev --name project-app-deploy -v ..:/var/www/project mybaseimage
86439874b8df561f529fde0d1e31824d70dc7e2a2377cd529331a2d7fcb00467
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
86439874b8df mybaseimage "/sbin/my_init" 4 seconds ago Up 3 seconds 22/tcp, 80/tcp project-app-deploy
40641f02a09b dockerfiles_app "/sbin/my_init" 2 minutes ago Up 2 minutes 0.0.0.0:2223->22/tcp, 0.0.0.0:8081->80/tcp project-app
I've solved my problem with the extend command in that way:
1) making changes into my ./dockerfiles/dev/build.yml file:
deploy-app:
extends:
file: ../base.yml
service: app
container_name: project-app-deploy
# set the build context to the project root
build: ../..
dockerfile: ./dockerfiles/dev/build-app/Dockerfile
environment:
APPLICATION_PLATFORM: "dev"
volumes:
- ../..:/var/www/project
2) run my deploy app container so:
$ docker-compose -f ./dockerfiles/dev/build.yml up -d deploy-app
Building deploy-app
...
Successfully built 74750fe274c6
Creating lovetime-app-deploy
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9bb2af79ffaa dev_deploy-app "/sbin/my_init" 5 seconds ago Up 4 seconds 22/tcp, 80/tcp project-app-deploy
812b8824f1f0 dockerfiles_app "/sbin/my_init" 3 minutes ago Up 3 minutes 0.0.0.0:2223->22/tcp, 0.0.0.0:8081->80/tcp project-app
$ docker inspect -f '{{ .Mounts }}' project-app-deploy
[{ ...... /var/www/project rw true}]
Update:
According to documentation, this command is not supported in newer compose versions:
The extends keyword is supported in earlier Compose file formats up to Compose file version 2.1 (see extends in v1 and extends in v2), but is not supported in Compose version 3.x.

Resources