Managing multiple Docker hosts can quickly become a daunting task; especially when talking about grouping Docker containers with Docker Compose, updating individual containers and let alone managing a separated development and production environment.

Set up Portainer

Portainer is a management UI for different Docker environments (Docker hosts and also Docker Swarm clusters). Portainer is very easy to use because it runs using a single container that can run on any Docker engine, regardless of the underlying operating system. Portainer allows you to manage Docker resources such as containers, images, volumes, networks, and more.

Spinning up Portainer is as simple as running the following commands. These commands will create a new Docker volume and start the container linked to the local Docker socket.

docker volume create portainer_data
docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer

If you are using Docker on Windows, you need to change the bound volume using the following command.

docker run -d -p 8000:8000 -p 9000:9000 --name portainer --restart always -v \\.\pipe\docker_engine:\\.\pipe\docker_engine -v portainer_data:C:\data portainer/portainer

Portainer binds ports 8000 and 9000, where port 9000 is the general port used by Portainer for the UI access. Port 8000 is used exclusively by the Portainer EDGE agent for the reverse tunnel function. If you do not plan to use the edge agent, you do not need to expose port 8000.

If you are using UFW to manage your host's network security, do not forget to add the correct ports to be accessible using these commands.

ufw allow 8000 comment "Portainer EDGE agent"
ufw allow 9000 comment "Portainer UI"

To deploy Portainer on Docker Swarm clusters, you should check out the Portainer's Deployment Guide.

Set up Watchtower

Watchtower automatically updates Docker container base images. If a new image gets pushed to Docker Hub or your image registry, Watchtower can automatically update the running version of your containerized application. Watchtower will pull down your new image, gracefully shut down your existing container, and restart it with the same options that were used when it was deployed initially.

Running Watchtower is as simple as executing the following command. Because we specify --clean, Watchtower will also remove orphaned images after restarting containers with new images.

docker run -d \
    --name watchtower \
    -v /var/run/docker.sock:/var/run/docker.sock \
    --restart=always containrrr/watchtower --cleanup

That's it; we now have an automatically updating Docker environment. Keep in mind; if you have any Docker containers you do not want to be automatically updated, you can use the following label to disable Watchtower for that specific container.

LABEL com.centurylinklabs.watchtower.enable="false"

Watchtower can run with a lot of additional arguments to match your needs. You can check them out in Watchtower's full documentation.

Managing your environment

By running the command docker ps, we can verify that both Portainer and Watchtower are running and bound to the right ports on your Docker host. Make sure that the status of both containers is Up like in the following example response.

CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS              PORTS                    NAMES
587e787bb0d6        portainer/portainer     "/portainer"             2 days ago          Up 2 days >9000/tcp   portainer
1c11115dc4c3        containrrr/watchtower   "/watchtower --clean…"   2 days ago          Up 2 days                                    watchtower

You can now access the UI of Portainer on port 9000, go to http://localhost:9000 or replace localhost with the IP address of your Docker host!

You can follow the steps show in the images below, once you have specified your desired username and password to log in, make sure to set the Docker environment to local.

That's all, you can now enjoy your automatically updating Docker environment!

Post image by kyohei ito