Introduction

I have been toying around with Docker for a few months now ever since I first bought a Raspberry Pi. It has been a great learning experience. Currently, I have over 20 self-hosted applications running in Docker. However, last week my power started to flicker and I began to wonder what would happen if my Raspberry Pi completely died?

My persistent data volumes for the containers are stored on a separate network file share in my NAS so I know they would be safe. What I would lose is all of my various environmental variables, port settings, and other miscellaneous settings that are included in my docker run codes. At the rate I am adding containers to my setup, it would take hours to recreate my environment. Then I discovered Docker Compose. Docker Compose allows me to store my docker environment in a single .yaml file and boot it up on any Docker host.

Basic Example

I presently use the docker run command to spin-up an application. It is simple, I just type the command in my terminal, hit enter, and in a few seconds my application is ready for access. The Gitea application container has a simple docker run code that I will use as an example:

docker run \ -p 3000:3000 \ -p 22:22 \ -v gitea:/data \ --restart always \ kunde21/gitea-arm:latest

I used Composerize to easily convert a standard docker run command to a format that I can place inside my docker-compose.yml file. In order to add this as a service in the file it would look like this:

version: '3.3' services: gitea-arm: ports: - '3000:3000' - '22:22' volumes: - 'gitea:/data' restart: always image: 'kunde21/gitea-arm:latest'

As you can see, the above docker-compose.yml file contains the same port mappings, volumes, options, and image as the original docker run command.

Example with Variables

Next is an example of a docker run command for a container that has many environmental variables. It is the MariaDB container that is maintained by LinuxServer.io.

docker run \ --name=mariadb \ -e PUID=1000 \ -e PGID=1000 \ -e MYSQL_ROOT_PASSWORD=ROOT_ACCESS_PASSWORD \ -e TZ=America/New_York \ -e MYSQL_DATABASE=USER_DB_NAME \ -e MYSQL_USER=MYSQL_USER \ -e MYSQL_PASSWORD=DATABASE_PASSWORD \ -p 3306:3306 \ -v path_to_data:/config \ --restart unless-stopped \ linuxserver/mariadb

After translating the above run command into a docker-compose.yml it comes out like this:

version: '3.3' services: mariadb: container_name: mariadb environment: - PUID=1000 - PGID=1000 - MYSQL_ROOT_PASSWORD=ROOT_ACCESS_PASSWORD - TZ=America/New_York - MYSQL_DATABASE=USER_DB_NAME - MYSQL_USER=MYSQL_USER - MYSQL_PASSWORD=DATABASE_PASSWORD ports: - '3306:3306' volumes: - 'path_to_data:/config' restart: unless-stopped image: linuxserver/mariadb

Bringing it all together

I combined my services into a single docker-compose.yml file as outlined below. This file can be placed on a private GitHub repository or a self-hosted git repository. Keeping the file on GitHub allows me to edit it very easily. GitHub also serves as an offsite backup for the file.

version: '3.3' services: gitea-arm: ports: - '3000:3000' - '22:22' volumes: - 'gitea:/data' restart: always image: 'kunde21/gitea-arm:latest' mariadb: container_name: mariadb environment: - PUID=1000 - PGID=1000 - MYSQL_ROOT_PASSWORD=ROOT_ACCESS_PASSWORD - TZ=America/New_York - MYSQL_DATABASE=USER_DB_NAME - MYSQL_USER=MYSQL_USER - MYSQL_PASSWORD=DATABASE_PASSWORD ports: - '3306:3306' volumes: - 'path_to_data:/config' restart: unless-stopped image: linuxserver/mariadb