Baeldung Pro – Ops – NPI EA (cat = Baeldung on Ops)
announcement - icon

Learn through the super-clean Baeldung Pro experience:

>> Membership and Baeldung Pro.

No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.

1. Overview

When working with Docker Compose, it’s not uncommon to run services that need to live only for a short time. In such cases, we may need the container to delete itself once it completes running. For this, we can implement the –rm flag when using docker-compose run. However, developers often wonder if it’s possible to configure this behavior directly in docker-compose.yml.

In this tutorial, we’ll discuss whether that’s possible, why it’s crucial, and how to correctly set up and run short-lived containers using Docker Compose.

2. Problem Statement

Let’s assume we have a service in our docker-compose.yml file that compiles assets, for instance, JavaScript or CSS. The container doesn’t need to stay alive. Once this container completes compiling, we may want it to output the result and automatically remove itself to prevent cluttering our system with unused containers.

Now, the main question is whether we can do this directly in the docker-compose.yml file. To answer this question, docker-compose.yml has no built-in setting to automatically remove a container after it runs. There’s no setting we can place in our YAML file to help carry out this task. Thus, we explore how to simulate this behavior.

3. Practical Example

In plain Docker, we can run:

$ docker run --rm my-image

Whereas, in Docker Compose, we can run:

$ docker-compose run --rm compiler

The –rm flag instructs Docker to automatically remove the container after it exits.

Here, we walk through a simple example, setting up a Node.js container that mounts our current directory and runs a build script inside.

Firstly, let’s create the docker-compose.yml file and paste the content below:

version: '3.8'

services:
  compiler:
    image: node:18
    working_dir: /app
    volumes:
      - .:/app
    command: ["npm", "run", "build"]

Next, let’s create a minimal package.json:

$ echo '{ "scripts": { "build": "echo Building..." } }' > package.json

Now, when we run:

$ docker-compose up compiler
Creating auto-remove_compiler_1 ... done
Attaching to auto-remove_compiler_1
compiler_1  | 
compiler_1  | > build
compiler_1  | > echo Building...
compiler_1  | 
compiler_1  | Building...
auto-remove_compiler_1 exited with code 0

Above, Docker Compose creates a long-living container. To clarify, it leaves the container behind in a stopped state after it runs and requires us to clean it up manually. The docker-compose up command is meant to start long-living services and manage their lifecycle. It assumes that we’d want to restart stopped containers or inspect them later. Well, this approach is not ideal for short tasks because, over time, our environment can be cluttered with old containers that we no longer need.

Let’s look at all the containers that are currently running and those that have exited:

$ docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS                     PORTS     NAMES
dfea9f20e95d   node:18   "docker-entrypoint.s…"   10 minutes ago   Exited (0) 5 minutes ago             auto-remove_compiler_1

While we can’t define auto-removal in the YAML file, we can still achieve auto-removal of a container using the –rm flag on the command line.

To run the compiler and remove the container automatically, we can run:

$ docker-compose run --rm compiler
Creating auto-remove_compiler_run ... done

> build
> echo Building...

Building...

When the npm run build command in our docker-compose.yml file completes, the compiled files stay in the project because of the Docker volume, and the container disappears, ensuring no cleanup is needed.

4. Automating the Process

To avoid using docker-compose run –rm repetitively, let’s wrap it in a shell script. For this, let’s create the Bash script auto_remove_container.sh and paste:

#!/bin/bash
echo "Compiling project..."
docker-compose run --rm compiler

Let’s run the Bash script auto_remove_container.sh:

$ bash auto_remove_container.sh
Compiling project...
Creating auto-remove_compiler_run ... done

> build
> echo Building...

Building...

Now, we can make our workflow simple and consistent.

5. Conclusion

In this article, we discussed the topic of auto-removing containers using docker-compose.yml.

The docker-compose.yml file doesn’t support the auto-removal of containers directly. However, we still can utilize docker-compose run –rm from the command line to achieve the task. As a result, we can keep our Docker environment clean and avoid clutter from containers that have already completed their tasks.

With the help of this approach, we can utilize Docker Compose to start and run both long-running services and short-lived tasks. As a result, we can eliminate the need for manual cleanup afterward.