---
title: Getting Started with Docker Compose
description: Learn how to set up a Docker compose stack with MariaDB and WordPress, including troubleshooting tips and interactive usage insights.
image: https://blog.rheinwerk-computing.com/hubfs/Getting%20Started%20with%20Docker%20Compose.png
---

[![Rheinwerk Computing Logo](https://blog.rheinwerk-computing.com/hubfs/computing_logo-header.svg)](https://blog.rheinwerk-computing.com/) [Blog](https://blog.rheinwerk-computing.com)

- Books 
    - Get an overview of our wide selection of books on every relevant computing topic. 
          - [General Computing](https://www.sap-press.com/rheinwerk-computing/general-computing/)
          - [DevOps](https://www.sap-press.com/rheinwerk-computing/devops/)
          - [Programming Languages](https://www.sap-press.com/rheinwerk-computing/programming-languages/)
          - [Security](https://www.sap-press.com/rheinwerk-computing/security/)
          - [Software Development](https://www.sap-press.com/rheinwerk-computing/software-development/)
- Book Subscription 
    - Get unlimited access to all Rheinwerk Computing books! 
          - [Programming Subscription](https://sap-press.com/subscriptions/)

[DevOps](https://blog.rheinwerk-computing.com/tag/devops)

# Getting Started with Docker Compose

![Rheinwerk Computing](https://blog.rheinwerk-computing.com/hubfs/RW-logo-300x300.png)  by [Rheinwerk Computing](https://blog.rheinwerk-computing.com/author/rheinwerk-computing)

In this blog post, we’ll provide an introductory example for the syntax of *docker-compose.yml.*

Thisdescribes a [Docker](https://learning.rheinwerk-computing.com/devops#docker)setup that consists of two services: a database server (MariaDB in the current version) and the WordPress content management system (CMS).

 

Most of the settings for the two services should be readily understandable:

- Named volumes are used to store the database files and [HTML](https://learning.rheinwerk-computing.com/html-and-css)files, respectively. (The names of the volumes must be specified *twice*, once in the description of the respective services and a second time—usually at the end of the *docker-compose.yml* file—in a separate volumes )
- In MariaDB, the wp database and the associated user wpuser are to be set up with the password secret. A random string can be used as root password because it’s not relevant for the setup.
- For WordPress to access the database, the corresponding WORDPRESS variables must be initialized. DB\_HOST references the service name db and the default port number of the MariaDB server.
- The web server responsible for WordPress uses port 80 in the container. This port should be connected to port 8082 of the host computer.

`# file test/docker-compose.yml`

`version: '3'`

 

`services:`

`   db:`

`      image: mariadb:latest`

`      volumes:`

`         - vol-db:/var/lib/mysql`

`      environment:`

`         MYSQL_RANDOM_ROOT_PASSWORD: 1`

`         MYSQL_DATABASE: wp`

`         MYSQL_USER: wpuser`

`         MYSQL_PASSWORD: secret`

`      restart: always`

 

`   wordpress:`

`      image: wordpress:latest`

`    volumes:`

`         - vol-www:/var/www/html/wp-content`

`      ports:`

`         - "8082:80"`

`      environment:`

`         WORDPRESS_DB_HOST: db:3306`

`         WORDPRESS_DB_USER: wpuser`

`         WORDPRESS_DB_NAME: wp`

`         WORDPRESS_DB_PASSWORD: secret`

`      restart: always`

`volumes:`

`   vol-www:`

`   vol-db:`

## “docker compose”

To try out [docker compose](https://blog.rheinwerk-computing.com/what-is-docker-compose), you must first go to the directory containing the file *dockercompose. yml*—here, the wordpress-example directory. Note that the directory name is used to name the containers, volumes, networks, and so on.

 

docker compose up -d then searches for the *docker-compose.yml* file in the current directory, downloads the required images (only if they aren’t already available, of course), creates the containers, connects them in a specifically created network, and starts them as background processes (option -d). The entire process takes only a few seconds (plus the time to download the images, if necessary). Note that because of restart: always, the containers are restarted automatically even after a reboot of the computer.

 

`cd wordpress-example             (directory with docker-compose.yml)`

`docker compose up -d`

`   Creating network wordpress-example_default" with the default`

`      driver`

`   Creating wordpress-example_wordpress_1 ... done`

`   Creating wordpress-example_db_1 ... done`

 

The docker ps command displays the two running containers (the output is heavily abridged due to space limitations). After a few seconds required to initialize the container, you can start using WordPress at the address, *localhost:8082*.

 

`docker ps`

`    ID          PORTS                   NAMES`

`    5211...     0.0.0.0:8082->80/tcp    wordpress-example_wordpress_1`

`    d9dc...     3306/tcp                wordpress-example_db_1`

 

To stop the execution of all related containers, you need to run docker compose stop. Similarly, docker compose start continues the execution. These commands each require *docker-compose.yml* to be in the current directory.

 

You can use docker compose down to stop and delete all the containers of the setups, while the volumes will remain intact. If necessary, you can redeploy the containers and keep the previous data using docker compose up:

 

`docker compose down             (stop and delete containers)`

`...`

`docker compose up -d            (set up new containers)`

 

If you want to delete the containers and their associated volumes, you should run the following commands for this example:

 

`docker compose down`

`docker volume rm wordpress-example_vol-db \`

`            wordpress-example_vol-www`

## “docker stack deploy”

Instead of using docker compose, you can also process the *docker-compose.yml* file via the docker stack deploy command. docker stack requires that the computer is a member of a Docker swarm. However, you absolutely don’t need to create a Docker cluster to use docker stack. It’s perfectly sufficient to run docker swarm init once on your machine. This way, your computer creates a swarm that consists of only one member.

 

`docker swarm init`

`   Swarm initialized: current node (eqbx...) is now a manager.`

`   To add a worker to this swarm, run the following command:`

`      docker swarm join --token SWMTKN-xxx 10.0.0.1:2377`

`   To add a manager to this swarm, run`

`   'docker swarm join-token manager' and follow the instructions.`

 

To deploy the containers described in *docker-compose.yml* along with a network, you must pass the file name of the compose file to docker stack deploy with the -c option and the name of the setup or stack as another parameter. This name will be prepended to the network, volume, and service names. (docker compose uses the name of the directory where *docker-compose.yml* is located instead of this name by default.)

 

`docker stack deploy -c docker-compose.yml stacktest`

`   Creating network stacktest_default`

`   Creating service stacktest_wordpress`

`   Creating service stacktest_db`

 

docker stack ls proves that the new stack has been set up and consists of two services:

`docker stack ls`

`NAME          SERVICES         ORCHESTRATOR`

`stacktest     2                Swarm`

 

You can now use docker service ls to verify that the services have actually been created and are up and running. As before, the output had to be shortened by a few columns:

 

`docker service ls`

`    ID              NAME                  REPLICAS    PORTS          ...`

`    skz4ab9p71va    stacktest_db          1/1`

`    ghdrn0z2gi5n    stacktest_wordpress   1/1         *:8082->80/tcp`

 

The REPLICAS column is decisive here. If it reads 0/1, an error occurred during startup. Information about the cause of the error can be obtained from the ERROR column of the output of docker service ps <sid/stackname>, where you pass the service ID or stack name as a parameter. The command specifies which tasks are executed in a service. The ERROR column is usually truncated to the point of being unrevealing. Then, the --notruncoption can provide help:

 

`docker service ps sometest --no-trunc`

`... NAME                 ... ERROR`

`stacktest_db.1               starting container failed: Invalid`

`address 10.0.1.14: It does not belong`

`to any of this network's subnets`

 

With docker ps, you can verify that a corresponding container has been created and launched for each service.

 

Unlike containers, there’s no way to stop and later restart stacks. However, you can delete the entire stack with all its services and networks using docker stack rm:

 

`docker stack rm stacktest`

`   Removing service stacktest_db`

`   Removing service stacktest_wordpress`

`   Removing network stacktest_default`

 

The volumes specified in *docker-compose.yml* are preserved in this process. For this reason, you can set up and rerun the stack later without losing any data:

 

`docker stack deploy -c docker-compose.yml stacktest`

 

When you no longer need the setup, you can delete both the stack and the mapped volumes:

 

`docker stack rm stacktest`

`docker volume rm stacktest_vol-db stacktest_vol-www`

 

## Debugging

Ideally, when the containers are started by docker compose up, everything goes well. But what happens if errors occur? A first means of troubleshooting is to run docker compose up without the -d option. This way, all logging output of all containers occurs directly in the console. So, to a certain extent, you can follow what’s going on in the containers.

 

Alternatively, you can use docker ps to take a look at the container list. There, you can usually tell immediately if there are containers that aren’t running as planned or that are constantly being restarted. You can then use docker logs <cname> to read the logging output of the affected containers. docker compose logs shows the combined logging of all containers in the group.

 

As usual, you can use docker exec to start an additional interactive shell process to look inside a running container:

 

`docker exec -it test_wordpress_1 /bin/sh`

 

`   ps -ax`

`      PID TTY     STAT    TIME COMMAND`

`      1 ?         Ss      0:00 apache2 -DFOREGROUND`

`      66 ?        S       0:00 apache2 -DFOREGROUND`

`      ...`

`      78 pts/0    Ss      0:00 /bin/sh`

`      83 pts/0    R+      0:00 ps -ax`

## Interactive Use

It’s not a good idea to specify an image in *docker-compose.yml* where no process is running permanently:

 

`# File docker-compose.yml`

`# Container/service ends immediately because`

`# there is no background process`

`version: '3'`

`services:`

`   myservice1:`

`      image: alpine`

 

If you now run docker compose up, the container in question will be set up and started, but the execution will again terminate immediately. The result looks similar when you run docker stack deploy, as the service gets set up and started, but due to the lack of a background process, its execution ends immediately. The swarm logic of Docker then keeps trying to start the service—but of course that doesn’t help either. The REPLICAS column of docker service ls shows 0/1, and docker service ps lists various startup attempts but shows no error messages:

 

`docker stack deploy -c docker-compose.yml test4`

 

`docker service ls`

`   ID             NAME                REPLICAS     IMAGE`

`   1t8cfulkpxoz   test4_myservice1    0/           alpine:latest`

 

`docker service ps 1t8cfulkpxoz`

`   ID            ...    DESIRED STATE     CURRENT STATE            ERROR`

`   kolqn5wnzgp2          Ready            Ready 4 seconds ago`

`   yrzb2d0g4arc          Shutdown         Complete 10 seconds ago`

`   y3ojrkgfv6sw          Shutdown         Complete a minute ago`

`   y54o8unhqf8s          Shutdown         Complete a minute ago`

`   xayg2njehiyj          Shutdown         Complete 2 minutes ago`

 

It will probably be an exceptional case, but it *is* possible to create a container for interactive use with docker compose. To do this, you must use docker compose to execute the run <servicename> command instead of up. The additional option --rm causes the container to be deleted after exiting the shell.

 

`docker compose run --rm myservice1`

 

`   cat /etc/os-release`

`      NAME="Alpine Linux"`

`      PRETTY_NAME="Alpine Linux v3.13"`

`      ...`

`   exit`

 

There’s no comparable interactive usage variant for docker stack deploy because docker stack is based on the concept of services, and the interactive operation of a service doesn’t make any sense

 

Editor’s note: This post has been adapted from a section of the book *[Docker: Practical Guide for Developers and DevOps Teams](https://www.sap-press.com/docker_5650/?utm_source=sappressblog&utm_medium=referral&utm_campaign=Blogs&utm_term=2383_chapter5-2&utm_content=2383)* by Bernd Öggl and Michael Kofler. Bernd is an experienced system administrator and web developer. Since 2001 he has been creating websites for customers, implementing individual development projects, and passing on his knowledge at conferences and in publications. Michael studied telematics at Graz University of Technology and is one of the most successful German-language IT specialist authors. In addition to Linux, his areas of expertise include IT security, [Python](https://learning.rheinwerk-computing.com/python), Swift, [Java](https://learning.rheinwerk-computing.com/java), and the Raspberry Pi. He is a developer, advises companies, and works as a lecturer.

 

This blog post was originally published 5/2024.

## Recommendation

[![Docker](https://blog.rheinwerk-computing.com/hs-fs/hubfs/social-suggested-images/2383-Oct-11-2023-04-48-18-4541-PM-1-2-1-1-1-2.jpg?width=170&name=2383-Oct-11-2023-04-48-18-4541-PM-1-2-1-1-1-2.jpg)](https://www.sap-press.com/docker_5650/?utm_source=sappressblog&utm_medium=referral&utm_campaign=Blogs&utm_term=2383_chapter5-2&utm_content=2383)

**Docker**

Learn the ins and outs of containerization in Docker with this practical guide! Begin by installing and setting up the platform. Then master the basics: get to know important terminology, understand how to run containers, and set up port redirecting and communication. You’ll learn to create custom images, work with commands, and use key containerization tools. Gain essential skills by following exercises that cover common tasks from packaging new applications and modernizing existing applications to handling security and operations.

[Learn More](https://www.sap-press.com/docker_5650/?utm_source=sappressblog&utm_medium=referral&utm_campaign=Blogs&utm_term=2383_chapter5-2&utm_content=2383)

![Rheinwerk Computing](https://blog.rheinwerk-computing.com/hubfs/RW-logo-300x300.png)

**by [Rheinwerk Computing](https://blog.rheinwerk-computing.com/author/rheinwerk-computing)**

Rheinwerk Computing is an imprint of Rheinwerk Publishing and publishes books by leading experts in the fields of programming, administration, security, analytics, and more.

[DevOps](https://blog.rheinwerk-computing.com/tag/devops)

[![Share on facebook](https://7528309.fs1.hubspotusercontent-na1.net/hub/7528309/hubfs/raw_assets/public/mV0_d-web-default-modules_hubspot/img/facebook-color.png?width=24&name=facebook-color.png)](https://www.facebook.com/share.php?u=https%3A%2F%2Fblog.rheinwerk-computing.com%2Fgetting-started-with-docker-compose%3Futm_medium%3Dsocial%26utm_source%3Dfacebook) [![Share on linkedin](https://7528302.fs1.hubspotusercontent-na1.net/hub/7528302/hubfs/raw_assets/public/mV0_d-web-default-modules_hubspot/img/linkedin-color.png?width=24&name=linkedin-color.png)](https://www.linkedin.com/shareArticle?mini=true&url=https%3A%2F%2Fblog.rheinwerk-computing.com%2Fgetting-started-with-docker-compose%3Futm_medium%3Dsocial%26utm_source%3Dlinkedin) [![Share on twitter](https://7528304.fs1.hubspotusercontent-na1.net/hub/7528304/hubfs/raw_assets/public/mV0_d-web-default-modules_hubspot/img/twitter-color.png?width=24&name=twitter-color.png)](https://twitter.com/intent/tweet?original_referer=https%3A%2F%2Fblog.rheinwerk-computing.com%2Fgetting-started-with-docker-compose%3Futm_medium%3Dsocial%26utm_source%3Dtwitter&url=https%3A%2F%2Fblog.rheinwerk-computing.com%2Fgetting-started-with-docker-compose%3Futm_medium%3Dsocial%26utm_source%3Dtwitter&source=tweetbutton&text=) [![Share on email](https://7528311.fs1.hubspotusercontent-na1.net/hub/7528311/hubfs/raw_assets/public/mV0_d-web-default-modules_hubspot/img/email-color.png?width=24&name=email-color.png)](mailto:?subject=Check+out+https%3A%2F%2Fblog.rheinwerk-computing.com%2Fgetting-started-with-docker-compose%3Futm_medium%3Dsocial%26utm_source%3Demail&body=Check+out+https%3A%2F%2Fblog.rheinwerk-computing.com%2Fgetting-started-with-docker-compose%3Futm_medium%3Dsocial%26utm_source%3Demail)

### Comments

### Latest Blog Posts

[![The Grafana-Docker Setup](https://blog.rheinwerk-computing.com/hs-fs/hubfs/The%20Grafana-Docker%20Setup.png?height=600&name=The%20Grafana-Docker%20Setup.png)](https://blog.rheinwerk-computing.com/the-grafana-docker-setup)

[DevOps](https://blog.rheinwerk-computing.com/tag/devops)

## [The Grafana-Docker Setup](https://blog.rheinwerk-computing.com/the-grafana-docker-setup)

[Read More](https://blog.rheinwerk-computing.com/the-grafana-docker-setup)

[![What Are Dockerfiles?](https://blog.rheinwerk-computing.com/hs-fs/hubfs/What%20Are%20Dockerfiles_.jpg?height=600&name=What%20Are%20Dockerfiles_.jpg)](https://blog.rheinwerk-computing.com/what-are-dockerfiles)

[DevOps](https://blog.rheinwerk-computing.com/tag/devops)

## [What Are Dockerfiles?](https://blog.rheinwerk-computing.com/what-are-dockerfiles)

[Read More](https://blog.rheinwerk-computing.com/what-are-dockerfiles)

**Subscribe to our blog!**Get notified about future blog updates.

- <https://www.linkedin.com/showcase/rheinwerk-computing/>
- <https://www.youtube.com/channel/UChj-U-uWGM7qRlHXSFU93ew>
- <https://blog.rheinwerk-computing.com/rss.xml>

### The official Rheinwerk Computing Blog

Rheinwerk Computing is an imprint of Rheinwerk Publishing and publishes resources that will help you accelerate your computing journey. The Rheinwerk Computing Blog is designed to provide helpful, actionable information on a variety of topics, including programming, administration, security, and analytics!

### Blog Topics

- [All Topics](https://blog.rheinwerk-computing.com)
- [Programming Languages](https://blog.rheinwerk-computing.com/tag/programming-languages)
- [How To](https://blog.rheinwerk-computing.com/tag/how-to)
- [JavaScript](https://blog.rheinwerk-computing.com/tag/javascript)
- [DevOps](https://blog.rheinwerk-computing.com/tag/devops)
- [Web Development](https://blog.rheinwerk-computing.com/tag/web-development)
- [Python](https://blog.rheinwerk-computing.com/tag/python)
- [What Is?](https://blog.rheinwerk-computing.com/tag/what-is)
- [Cybersecurity](https://blog.rheinwerk-computing.com/tag/cybersecurity)
- [Software Development](https://blog.rheinwerk-computing.com/tag/software-development)
- [Java](https://blog.rheinwerk-computing.com/tag/java)

### Blog curated by

[![Rheinwerk Computing Logo](https://blog.rheinwerk-computing.com/hubfs/computing_logo-header.svg)](https://www.sap-press.com/rheinwerk-computing/) [Visit Rheinwerk Computing Store](https://www.sap-press.com/rheinwerk-computing/)

### About

- [Home](https://sap-press.com/)
- [About Us](https://sap-press.com/the-publisher/)
- [Contact](mailto:info@rheinwerk-publishing.com)
- [Legal Notes](https://sap-press.com/legal-notes/)
- [Privacy Policy](https://sap-press.com/privacy/)
- [Terms of Use](https://sap-press.com/terms/)

© 2026 Rheinwerk Publishing, Inc. | Change Privacy Options

```json
{
  "@context" : "https://schema.org",
  "@type" : "BlogPosting",
  "author" : {
    "@type" : "Person",
    "name" : "Rheinwerk Computing",
    "url" : "https://blog.rheinwerk-computing.com/author/rheinwerk-computing"
  },
  "dateModified" : "2025-04-23T13:56:04.571Z",
  "datePublished" : "2024-05-28T13:00:00.000Z",
  "headline" : "Getting Started with Docker Compose",
  "image" : [ "https://blog.rheinwerk-computing.com/hubfs/Getting%20Started%20with%20Docker%20Compose.png" ],
  "mainEntityOfPage" : {
    "@id" : "https://blog.rheinwerk-computing.com/getting-started-with-docker-compose",
    "@type" : "WebPage"
  },
  "publisher" : {
    "@type" : "Organization",
    "logo" : {
      "@type" : "ImageObject",
      "url" : "https://blog.rheinwerk-computing.com/hubfs/Logo-1.jpg"
    },
    "name" : "Rheinwerk Publishing, Inc."
  }
}
```