How to Install & Use Docker Compose on Ubuntu 18.04

Docker Compose is a tool that helps you define and run multi-container applications. Instead of you building, running and connecting containers from separate Dockerfiles, it allows you to use a YAML file (called the Compose file) to define all of your application’s services, after which you can create and start them by using a single command.

Some of the most popular uses of Docker Compose include single application deployments, automated testing and local development.

In this tutorial we’ll learn how to install Docker Compose by the end of it, you should have a basic understanding of some of its’ commands and how it works.

NOTE: Even though this tutorial is written for Ubuntu 18.04, the commands should apply to other operating systems as well.


  1. A non-root sudo user. You can check our tutorial [How to Create a Sudo User on Ubuntu] to see how to set it up.
  2. Docker installed and optionally allowing non-sudo access to Docker. To do this, you can follow Step 1 and Step 2 from our previous tutorial – [How to Install & Use Docker on Ubuntu 18.04]

NOTE: Since it’s optional for readers to allow non-sudo access to Docker, the command examples will have sudo appended to the docker command, for those who have not enabled non-sudo access.

Step 1 — Install Docker Compose

Check the latest Docker Compose releases here, and replace the version in the following command ( 1.23.2 ) with the version you see tagged as the Latest release, to download the latest version:

$ sudo curl -L -s-uname -m -o /usr/local/bin/docker-compose

Set executable permissions to the Docker Compose binary:

$ sudo chmod +x /usr/local/bin/docker-compose

Check if the installation was successful by checking the Compose version:

$ docker-compose --version

The output should look something like this:

docker-compose version 1.23.2, build 1110ad01

Step 2 — Docker Compose Basics

With Docker Compose installed we can get to running our first container using it. We’ll use the well known Hello World example. To do this we’ll create our first Compose file.

The Compose files are YAML files, and one of the default names that Docker Compose looks for is called docker-compose.yml.

If you want to name the Compose file something else, then you have to use the -f argument followed by the alternate file name.

Now let’s create a directory for the YAML file and move into it:

$ mkdir hello-world
$ cd hello-world

Use your preferred text editor and create the docker-compose.yml file:

$ nano docker-compose.yml

Add the following contents in the file:

  image: hello-world

Let’s see what each line means:

my-test – will be used as part of the container name
image: hello-world – we’re telling Docker Compose to use the image by the name hello-world. Just like when we use docker run hello-world, it will search locally and if it doesn’t find it, it’ll try to pull it from Docker Hub.

Save and exit the file when you’re finished.

While we’re still in the ~/hello-world directory, we’ll execute the following command:

$ sudo docker-compose up

Now, just like when running docker run hello-world, it’ll search locally for the hello-world image, and download it from Docker Hub if it doesn’t find it.

The output will look something like this when it’s finished:

Pulling my-test (hello-world:)...
latest: Pulling from library/hello-world
d1725b59e92d: Pull complete
Creating hello-world_my-test_1 ... done
Attaching to hello-world_my-test_1

After pulling the image, Docker Compose creates a container from it, attaches, and runs the [hello] program, which then outputs the message confirming that the installation is working and explains the steps that Docker ran through:

my-test_1  | 
my-test_1  | Hello from Docker!
my-test_1  | This message shows that your installation appears to be working correctly.
my-test_1  | 
my-test_1  | To generate this message, Docker took the following steps:
my-test_1  |  1. The Docker client contacted the Docker daemon.
my-test_1  |  2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
my-test_1  |     (amd64)
my-test_1  |  3. The Docker daemon created a new container from that image which runs the
my-test_1  |     executable that produces the output you are currently reading.
my-test_1  |  4. The Docker daemon streamed that output to the Docker client, which sent it
my-test_1  |     to your terminal.

Since Docker containers only run as long as the command is active, the container stopped after the hello program finished running.

We can see that the container is stopped by checking active containers:

$ sudo docker ps


CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES

And if we check all of the containers, by using the -a flag, we can see the container created:

$ sudo docker ps -a


CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                         PORTS               NAMES
17cd42c3da63        hello-world         "/hello"            About an hour ago   Exited (0) About an hour ago                       hello-world_my-test_1

Using this information, we can remove the container when we’re done with it, to keep things clean. We can remove the container by using the docker rm command, followed by the name or ID of the container:

$ sudo docker rm hello-world_my-test_1


$ sudo docker rm 17cd42c3da63

When all the containers referencing an image are removed, we can also remove the image by using the docker rmi command:

$ sudo docker rmi hello-world

You can check out the details and examples on how the rmi subcommand works in the official Docker documentation

Step 3 — Docker Compose Commands

So we ran docker-compose up to run a container which ran the hello program that displayed the output message and then exited. This is not ideal, however. What we want is for docker-compose to act more like a service.

The Hello World container exits after it’s run, so we’ll need a container that keeps running.

Starting a Container as a Background Process

For this example we’ll use nginx.

Let’s set up a new directory for nginx and move into it:

$ mkdir ~/nginx
$ cd ~/nginx

Now create the docker-compose.ymlfile and paste the following content:

  image: nginx

Save and exit the file when you’re finished.

Now we’ll run the nginx container as a background process by running docker-compose up and by adding the -d switch, which tells it do detach.

NOTE: If we don’t add the -d switch, then we’d have to type Ctrl+C to exit the process.

To start the container and detach, run:

$ sudo docker-compose up -d

The nginx image will be downloaded and the container will be started in the background.

We can see our active containers with the command:

$ sudo docker ps

The output looks something like this:

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
ff9d47aa7014        nginx               "nginx -g 'daemon of…"   9 minutes ago       Up 3 seconds        80/tcp              nginx_nginx_1

Interacting with a Running Container

If you need to interact with a running container, we can do so by using the docker exec command, followed by its’ ID or name, to start a shell inside the running container:

$ sudo docker exec -it nginx_nginx_1 /bin/bash

The -t switch opens up a terminal, the -i switch makes it interactive, and by using the /bin/bash option we’re opening a bash shell in the running container.

You’ll notice your prompt change to root@container_id:/# :


You can now work from the command prompt.

IMPORTANT: Keep in mind, however, that unless you are in a directory that is part of a data volume ( a linked path on the host machine that can be used by the container ) , your changes will disappear when the container restarts.


That covers installing Docker Compose and a basic usage of it, however there’s more to learn in order to really have fun with it.

To see the full list of configuration options for the docker-compose.yml file, please check the official Docker Documentation and refer to the Compose file reference.

If you’ve found any issues with this tutorial, or have any questions, then please do not hesitate to contact us.

Also, if you’re looking for a high performance VPS, then do check out our KVM SSD Plans. Our offer starts at 1GB RAM + 10GB SSD at just $9.99/mo.

Notify of
Inline Feedbacks
View all comments
× Dracula Servers

Subscribe to DraculaHosting and get exclusive content and discounts on VPS services.