I'm currently running an executable in Docker that has been mounted as a Docker volume in the foreground. The executable (or the service) continuously generates console output and can be interrupted by the Ctrl-C signal. From time to time, I have to update the service executable "manually". To do this, I wrote a sh
script that temporarily stops the Docker container, downloads the new executable, unpacks it and restarts the Docker container. Is this a common way for my use case? Or can I update it in the container itself?
Below parts from:
docker-compose.yml
myservice:
image: debian:12
init: true
stop_grace_period: 1m
user: 1000:1000
volumes:
- /home/tobi/myservice/:/myservice/
command: >
bash -c "cd /myservice/ && ./myserviceExec"
labels:
- "traefik.enable=true"
- "traefik.http.routers.myservice.rule=Host(`sub.mydomain.com`)"
- "traefik.http.services.myservice.loadbalancer.server.port=80"
- "traefik.http.routers.myservice.entrypoints=websecure"
- "traefik.http.routers.myservice.tls.certresolver=myresolver"
update_script.sh
#!/bin/sh
docker stop proxy-myservice-1
sleep 5
sh script_backup.sh
sleep 5
wget https://...afile.zip
sleep 5
unzip afile.zip
sleep 5
mv -v myserviceExec myservice/
rm -v afile.zip
sleep 5
docker start proxy-myservice-1
sleep 5
ls -la --color=auto
ls -la --color=auto myservice/
sleep 30
docker logs -t proxy-myservice-1
-
1\$\begingroup\$ Interesting way to use containers. Why can't you either run the executable/service directly, or package it properly as a Docker image? Then when it's time to update, you rebuild and launch the new image. \$\endgroup\$TomG– TomG2024年05月03日 09:42:52 +00:00Commented May 3, 2024 at 9:42
-
\$\begingroup\$ @TomG I can run the executable directly, but I want to use it as a service in a Docker Compose context, firstly, because I want to use traefik as proxy. A separate image would also be much more complex to maintain. \$\endgroup\$Tobias Grothe– Tobias Grothe2024年05月03日 13:29:18 +00:00Commented May 3, 2024 at 13:29
-
\$\begingroup\$ Did you code the executable yourself? What language? There's probably base images available for the technology you are using. Sometime it's worth doing things "the right way". If you host the code on e.g. GitHub, you can have actions build the image for you on any action you specify. \$\endgroup\$TomG– TomG2024年05月03日 20:34:41 +00:00Commented May 3, 2024 at 20:34
-
\$\begingroup\$ "Did you code the executable yourself?" No, it's closed source. \$\endgroup\$Tobias Grothe– Tobias Grothe2024年05月04日 00:13:53 +00:00Commented May 4, 2024 at 0:13
1 Answer 1
Your manual approach, using a single docker container, sounds like it is routinely accompanied by a brief outage as you switch to a new rev of code.
Is this a common way
No.
can I update it in the container
Yes, but I wouldn't recommend it. Let the container query an endpoint to learn the current rev of code, probably an executable name with a SemVer suffix. When it changes, download the new code, ask the current daemon to exit, and respawn on the same TCP port.
Here is a better and more common approach. A load balancer listens for internet client requests on some well known (address, port), and distributes requests to multiple backends which routine healthchecks have shown are currently up. Healthy backends are "in the rotation", getting a share of incoming requests.
When you rev the code, deploy new containers with that code so they will be added to the rotation. Once they are seen to be working correctly, tear down containers running downrev code.
-
\$\begingroup\$ "sounds like it is routinely accompanied by a brief outage as you switch to a new rev of code." That is correct. But I could also replace the file during operation and then simply call
docker restart
. What do you think? \$\endgroup\$Tobias Grothe– Tobias Grothe2024年05月03日 13:35:14 +00:00Commented May 3, 2024 at 13:35