If you're already using Docker, you might came across Docker Compose.
The idea of Docker Compose is to help you to define and build application stacks.
These application stacks are basically multiple containers that can be linked together to provide a multi-container-service.
For instance, you can use Docker Compose to launch a three container application stack that has a load balancer, a web application and a database. Each application runs in its own container, but Docker Compose allows you to start the complete application stack without having to link and configure each container.
In a Docker Compose configuration file you can define environment variables, networks or volumes. A developer can simply use docker-compose up to start the application stack, which makes it easy to create a development environment which behaves identically on every developers machine. I think every developer knows the situation where she or he joins a new team and wants to setup the new project immediately - Docker Compose can speed this up.
Another scenario for Docker Compose are single host deployments. Docker Compose was originally created for development purposes, but there are production environment features like restart policies or container scaling. There is a more detailed description available in the official Docker documentation (which is always a good resource for getting help). However, for more complex setups, one would use Docker Swarm or even Kubernetes.
If you're using Docker for Mac or Docker for Windows, Docker Compose is already installed on your machine. If you want to run Docker Compose on a Linux server, please check the installation instructions.
In your terminal, you can type docker-compose -v to check if Docker Compose is installed and which version you are currently using. If everything is correct, you should see something like docker-compose version 1.22.0, build f46880f.
The following article will explain the basic usage of Docker Compose. You will create a MySQL database, a WordPress instance and an NGINX proxy.
An empty directory, where you can create a docker-compose.yml file.
.
The first section defines the database service. The user credentials as well as the default database are configured with environment variables. For security reasons, the root user is created with a random password.
There is no need to access the database from the outside (only the WordPress container needs to access it), so no ports are exposed.
The database service is a member of the backend network, which makes it possible for WordPress to read and store data.
We are using the official WordPress image from the Docker Hub. As you have already seen in the database service, we use some environment variables to configure the container - in this case, the database connection is configured.
WordPress is not directly accessible, so that there is no need to open any ports.
The container is a member of both networks (backend and frontend).
The NGINX service acts as a proxy for WordPress - all requests are routed through it.
To make the NGINX proxy available for the outside, it is necessary to expose a port (in this case we are mapping port 8080 to 80). Furthermore, it needs to communicate with the wordpress service, thats why it is a member of the frontend network.
There is also a volume mapping which mounts the NGINX configuration file into the correct directory.
If applications need to communicate with each other, you'll have to define networks. In our docker-compose.yml the networks are defined in the last three lines. There are different networks for the backend and frontend.
The Wordpress container is assigned to both networks (backend and frontend), because Wordpress needs access to the MySQL server and the NGINX instance will proxy requests to WordPress.
PING wordpress (172.20.0.2) 56(84) bytes of data.
If two or more services are a member of the same network, it is possible to reach them via their defined names (in this example database, wordpress and nginx).
Typically, your files are deleted once you stop and remove your application stack. If you need to have your data to be persistent, you can use volumes. Your data is then stored inside the volume which is independent from your container's lifetime.
Besides of making data persistent, volumes can be used to mount files into a running container. In this example, the NGINX default.conf is mounted into the NGINX configuration directory.
A more detailled explanation on volumes, I refer to the use volumes section in the official documentation.
There are situations, where it is mandatory, that a container is already runinng before another is started. To ensure this, you can use the depends_on property. In our Docker Compose configuration file the NGINX container will be started once the WordPress container is ready.
However Docker Compose won't wait for your database to be ready (even if you're using depends_on) - it will only make sure that the services are started in the correct order.
If you have to wait for a database to be successfully started and accept connections, you will need to use a tool such as wait-for-it or dockerize. For further information about this topic, Control startup order in Compose is a good reading.
According to the Twelve-Factor App it is a good practice to pass the app config as environment variables.
If you have a look at the definition of the database and wordpress services, you'll notice that both services are configured with environment variables.
Typically the description of a Docker image provides a very good overview of available environment variables. Have a look at the MySQL and WordPress image in the Docker Hub.
It's now time to start the application. You can start your stack by typing docker-compose up --build. Of course, you need to make sure that you execute the command from within the directory where the docker-compose.yml is located.
By default docker-compose uses the docker-compose.yml, but you can also specify an alternate Docker Compose configuration file by using the -f (or --file) option (e.g. docker-compose -f docker-compose.production.yml up --build).
Once the application stack is successfully started, you can navigate to http://localhost:8080 which will bring up the WordPress setup wizard.
If you have completed the setup routine, you can login to the admin interface or open the blog.
Docker Compose significantly simplifies your development workflow. Whether you're using it to set up a one-container-only stack or a complex multi-service-architecture, you can easily configure your application and share it with other developers in your team. Think about how much time you've spent helping others to start the application on their machine - now you just need to share the docker-compose.yml. Another benefit is, that reading the docker-compose.yml will give others a first insight of how your application stack behaves and which services communicate with each other.
If you don't need automatic scaling or multi-server-environments, you can even use Docker Compose to run your application in production.
Special thanks to Philipp for proofreading this article.
Software Engineer. Always curious for new (☁️) technologies. Working on all stacks. Using Java, TypeScript, Bash, Docker, Kubernetes, macOS, ...
And it works in most cases, its true that I might have been just lucky for hundreds of docker-compose ups.
Note: I stole it from somewhere, and I do not remember the original author.
Cheers.
Awesome work.
(Opinion) Architect VS Engineer VS Developer.
Software Engineer. Always curious for new (☁️) technologies. Working on all stacks. Using Java, TypeScript, Bash, Docker, Kubernetes, macOS, ...
Sore eyes?
dev.to now has dark mode.
We're a place where coders share, stay up-to-date and grow their careers.
We strive for transparency and don't collect excess data.
