docker-compose
container naming
dash vs underscore
containerization
Docker tips

docker-compose container name use dash - instead of underscore _

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

Docker Compose uses dashes (-) rather than underscores (_) by default when generating container names because dashes are valid in DNS hostnames while underscores are not. Since Docker uses container names for internal DNS resolution on custom networks, dash-based names work seamlessly for inter-container communication. Understanding this convention helps avoid networking issues in multi-container applications.

How Docker Compose Names Containers

By default, Docker Compose generates container names using the pattern {project}_{service}_{index} (Compose V1) or {project}-{service}-{index} (Compose V2):

yaml
1# docker-compose.yml
2services:
3  web-app:
4    image: nginx
5  api-server:
6    image: node:18
bash
1# Compose V2 (default in modern Docker)
2docker compose up -d
3docker ps --format '{{.Names}}'
4# myproject-web-app-1
5# myproject-api-server-1
6
7# Compose V1 (legacy)
8docker-compose up -d
9# myproject_web-app_1
10# myproject_api-server_1

Setting a Custom Container Name

Use the container_name property to override the generated name:

yaml
1services:
2  web:
3    image: nginx
4    container_name: my-web-server    # Explicit name with dashes
5    ports:
6      - "80:80"
7
8  api:
9    image: node:18
10    container_name: my-api-service
11    ports:
12      - "3000:3000"

With container_name set, Docker uses exactly that name regardless of the project name.

Why Dashes Over Underscores

DNS Compatibility

Containers on the same Docker network can reach each other by name. Docker's internal DNS follows RFC 952 and RFC 1123, which allow only letters, digits, and hyphens in hostnames:

yaml
1services:
2  web:
3    container_name: web-frontend    # Valid DNS hostname
4    networks:
5      - app-network
6
7  api:
8    container_name: api-backend     # Valid DNS hostname
9    networks:
10      - app-network
11
12networks:
13  app-network:
bash
1# From the web container, this works:
2curl http://api-backend:3000/health
3
4# With underscores, DNS resolution may fail on some configurations:
5# curl http://api_backend:3000/health  # May not resolve

Docker Service Discovery

In Docker Swarm and Compose, service names are used as DNS entries. Underscores in these names can cause resolution failures with certain DNS resolvers:

yaml
1# Good — works reliably
2services:
3  user-service:
4    image: myapp/user-service
5
6# Potentially problematic
7services:
8  user_service:
9    image: myapp/user-service

The Project Name

The project name (prefix for container names) defaults to the directory name. You can set it explicitly:

yaml
1# docker-compose.yml
2name: my-project    # Compose V2
3
4services:
5  web:
6    image: nginx
bash
1# Or via environment variable
2COMPOSE_PROJECT_NAME=my-project docker compose up
3
4# Or via CLI flag
5docker compose -p my-project up
MethodExample
DefaultDirectory name
name in compose filename: my-project
-p flagdocker compose -p my-project up
COMPOSE_PROJECT_NAMEEnvironment variable
.env fileCOMPOSE_PROJECT_NAME=my-project

Scaling and Container Names

container_name prevents scaling because each container needs a unique name:

yaml
1services:
2  worker:
3    image: myapp/worker
4    container_name: my-worker    # Cannot scale!
5
6  # Without container_name — can scale
7  processor:
8    image: myapp/processor
9    # Name will be: myproject-processor-1, myproject-processor-2, etc.
bash
1# This fails with container_name set:
2docker compose up --scale worker=3
3# ERROR: container name "my-worker" is already in use
4
5# This works without container_name:
6docker compose up --scale processor=3

Compose V1 vs V2 Naming

bash
1# Compose V1 (docker-compose command)
2# Uses underscores as separator
3myproject_web_1
4myproject_api_1
5
6# Compose V2 (docker compose command)
7# Uses dashes as separator
8myproject-web-1
9myproject-api-1

If you are migrating from V1 to V2 and have scripts that reference container names with underscores, update them to use dashes or set explicit container_name values.

Common Pitfalls

  • Underscore DNS failures: Container names with underscores may not resolve via Docker's internal DNS on custom networks. Always use dashes for names that will be used in inter-container communication.
  • Scaling conflict: Setting container_name prevents docker compose up --scale from working. Only use container_name when you need exactly one instance of a service.
  • V1/V2 migration: Switching from docker-compose (V1) to docker compose (V2) changes the separator from underscore to dash. Scripts or configs referencing old names will break.
  • Project name from directory: If your project directory has spaces or special characters, the auto-generated project name may cause issues. Set it explicitly via name: in the compose file.
  • Unique names required: container_name must be unique across all running containers on the host, not just within the compose project. Conflicts with containers from other projects will prevent startup.

Summary

  • Docker Compose V2 uses dashes as separators in generated container names (project-service-index)
  • Dashes are preferred because they are valid DNS hostname characters; underscores may cause resolution failures
  • Use container_name to set an explicit name, but this prevents scaling
  • The project name defaults to the directory name — set it explicitly with name: or -p flag
  • When migrating from Compose V1 to V2, update any references from underscore-based to dash-based container names

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design