Container setup
Overview
A lot of services will be installed using docker containers for ease of use. This way services can be swapped, upgraded or changed almost at will while still being able to store persistent data easily. Performing backups will be also made easy, since the containers themselves don't need to be backed up.
Docker compose
Docker services are usually run by one of two ways. Either by using the docker run
command or by using docker compose
. While both ways have their pros and cons, using docker compose
is often much more comfortable.
docker compose
takes a file called docker-compose.yml
and runs the services that are configured in it. The file can include one or more services (often forming an app-stack), that can each be configured together with additional settings like volumes or networks.
It is possible to put every single service you want to use inside a single docker-compose.yml
file or alternatively create seperate files for seperate app-stacks.
The following shows a small docker-compose.yml
file for an example app.
services:
app1:
image: app1
ports:
- "8080:80"
volumes:
- ./config:/config
- /path/to/persistentdata/app1:/var/log
environment:
- hostname=${HOSTNAME}
depends_on:
- redis
redis:
image: redis
The compose file specifies two services: app1
and redis
. We can see some different things like persistent storage via docker volumes, environment variables with .env
or port mappings.
With - "8080:80"
the port 80 inside the container will be mapped to the port 8080 outside the container. If for example the app starts a webserver that internally runs on port 80, then it can be accessed over port 8080 outside the container.
For a more detailed overview see the docker compose documentation.
.env
Some settings can be stored outside of the docker-compose.yml
file and insted inside the .env
file. This way, repeating settings like a database username or specific port can be specified at a single point, making later changes much easier.
An example .env
file can look like this:
DB_USER=dbusername
DB_PASS=secretpassword
APP_PORT=9876
In the docker-compose.yml
file, these variables can be accessed by simply writing ${DB_USER}
. When starting the container, the variable gets substituted by the entry in the .env
file.
More information can be found in the docker documentation.
Persistent Storage
For persistant storage of data (e.g. documents, pictures, videos, etc.) we can use docker volumes. A volume can be used like this:
services:
app1:
volumes:
- ./config:/conf
Here, the config
folder, which sits right beside the docker-compose.yml
folder outside the container, will be mapped to the conf
folder inside the container. This lets the container read and write (usual permissions apply) to the folder, making it possible to persistently store data. When the container gets destroyed, all data in the config
folder will be left untouched. The volumes will be created by docker if they do not exist when starting up the container.
Docker Networks
By default, if no additional configuration is specified, docker automatically creates a single default docker network for all services in the compose file. For better configuration possibilities we can specify a different docker network for the services to use. We can also set some things like the type of network, the subnet used by the network or if IPv6 should be supported.
To specify a different network we can for example write the following:
networks:
default:
name: bookstack
driver: bridge
This creates a new network called bookstack
that uses the default bridge
network driver. By using default
, every container, unless set otherwise, will be put into the newly created network.
By creating a network by ourselves we can make it possible for other services, that may be created somewhere else, to join the network