I’ve been a bit of an old school “just use docker” vs. “docker-compose”, but it was the other day when I learned that they’ve now baked “compose” into the base docker cli. This means there is less reason to avoid using the features of docker compose.
Still, as previously discussed, I like using Makefiles to manage my containers. There is a very good argument to adopt using Watchtower, despite it being not recommended.
We do not endorse the use of Watchtower as a solution to automated updates of existing Docker containers. In fact we generally discourage automated updates.
Let me go on record that if you’re going to blindly run your update process, you may as well just use Watchtower. This is a good way to automatically break things of course, so maybe don’t auto-update things that you rely on to work (like wireguard or your web server).
With that out of the way – let me point out one of the downsides to my previous Makefile approach to managing containers: I’d slowly run out of disk space with many old images. I had gotten into the habit of running
1 |
$ docker system prune |
every once in a while. This would get rid of all the containers, and images, that were no longer active. It did have the downside of removing images that were not currently running – so you need to be aware of that if you had assumptions.
Still my makefile approach saved me a few times allowing me to easily re-name / re-run the -old
version of a container and back out of a bad update.
What I needed to do was make sure that the old, -old
image was removed. This was where most of the disk space growth was. This turns out to be easier to do than to explain. Here is my update makefile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# # comment # https://hub.docker.com/r/project/name # NAME = containername REPO = project/name:latest # ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) # Create the container build: docker create \ --name=$(NAME) \ -p 8000:3000 \ -e VARIABLE=true \ -v $(ROOT_DIR)/config/:/path/in/container/ \ --restart=unless-stopped \ $(REPO) # Start the container start: docker start $(NAME) # Update the container update: docker pull $(REPO) $(eval IMAGEID:=$(shell docker container inspect --format '{{.Image}}' $(NAME)-old)) - docker rm $(NAME)-old - docker rmi $(IMAGEID) docker rename $(NAME) $(NAME)-old make build docker stop $(NAME)-old make start |
There are only two new lines. The first is
1 |
$(eval IMAGEID:=$(shell docker container inspect --format '{{.Image}}' $(NAME)-old)) |
This is assigning the variable IMAGEID
to have the docker image id value from the current -old
image.
The second is the obvious removal of the image based on that id.
1 |
- docker rmi $(IMAGEID) |
I believe that these two additional lines result in nearly no filesystem growth as I update images. Very handy as some of the linuxserver.io images pull down ~1GB of data every time, and they are updated weekly.