Setting Up a LAMP Stack with Docker Compose
Docker Compose is a tool that allows to declare which Docker containers should run, and which relationships should exist between them. It follows the infrastructure as code approach, just like most automation software and Docker itself.
Contents
The docker-compose.yml
File
When using Docker Compose, the Docker infrastructure must be described in a YAML file called docker-compose.yml
.
Let's see an example:
version: "3" services: web: image: "apache:${PHP_VERSION}" restart: 'always' depends_on: - mariadb restart: 'always' ports: - '8080:80' links: - mariadb mariadb: image: "mariadb:${MARIADB_VERSION}" restart: 'always' volumes: - /var/lib/mysql/data:${MARIADB_DATA_DIR - /var/lib/mysql/logs:${MARIADB_LOG_DIR - /var/docker/mariadb/conf:/etc/mysql environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_DATABASE: ${MYSQL_DATABASE} MYSQL_USER: ${MYSQL_USER} MYSQL_PASSWORD: ${MYSQL_PASSWORD}
In the first line we declare that we are using the version 3 of the Docker compose language.
Then we have the list of services, namely the web
and the mariadb
services.
Let's see the properties of the services:
port
maps the 8080 container port to the 80 host system port. This is very useful for a development environment, but not in production, because it allows us to connect our browser to the containerized web server. Normally there is no need to connect to MariaDB from the host system.links
declares that this container must be able to connectmariadb
. The hostname is the container name.depends_on
declares thatmariadb
needs to start beforeweb
. This is because we cannot do anything with our application until MariaDB is ready to accept connections.restart: always
declares that the containers must restart if they crashes.volumes
creates volumes for the container if it is set in a service definition, or a volume that can be used by any container if it is set globally, at the same level asservices
. Volumes are directories in the host system that can be accessed by any number of containers. This allows to destroy a container without losing data.environment
sets environment variables inside the container. This is important because setting these variables we set the MariaDB root credentials for the container.
About Volumes
It is a good practice to create volumes for:
- The data directory, so we don't lose data when a container is created or replaced, perhaps to upgrade MariaDB.
- The directory where we put all the logs, if it is not the datadir.
- The directory containing all configuration files (for development environments), so we can edit those files with the editor installed in the host system. Normally no editor is installed in containers. In production we don't need to to this, because we can copy files from a repository located in the host system to the containers.
Using Variables
In the above example you can see several variables, like ${MARIADB_VERSION}
. Before executing the file, Docker Compose will replace this syntax with the MARIADB_VERSION
variable.
Variables allow to make Docker Compose files more re-usable: in this case, we can use any MariaDB image version without modifying the Docker Compose file.
The most common way to pass variables is to write them into a file. This has the benefit of allowing us to version the variable file along with the Docker Compose file. It uses the same syntax you would use in BASH:
PHP_VERSION=8.0 MARIADB_VERSION=10.5 ...
For bigger setups, it could make sense to use different environment files for different services. To do so, we need to specify the file to use in the Compose file:
services: web: env_file: - web-variables.env ...
Docker Compose Commands
References
More details can be found in the Docker documentation:
Docker Compose Resources
- Overview of Docker Compose in the Docker documentation
- Compose file in the Docker documentation
- Docker Compose on GitHub
Content initially contributed by Vettabase Ltd.