Home > other >  How to control docker compose containers from within container?
How to control docker compose containers from within container?

Time:11-28

I have this minimal reproducible example of a docker compose file and I want to be able to control all docker compose services from within a docker container (docker-in-docker).

Example docker-compose.yml:

version: '3'

services:
  redis:
    image: redis

  node:
    image: node

First I start all with: docker compose -f docker-compose.yml up -d

When I run docker compose ps on the docker host I get the correct output:

NAME      COMMAND                  SERVICE             STATUS              PORTS
node-1    "docker-entrypoint.s…"   node                exited (0)          
redis-1   "docker-entrypoint.s…"   redis               running             6379/tcp

Running the same command from within a container with the binded docker socket as

docker run -it \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /current_directory/:/tmp/ \
  docker/compose -f /tmp/docker-compose.yml ps

doesn't list the containers:

Name   Command   State   Ports
------------------------------

I am aware that docker/compose runs on docker compose version 1.26.2, but even building my own container with docker compose v2.1.1 and running the same (adopted) command produces an empty list, too. I also tried the approach described here with setting the owner of the socket file but with the same result as before.

Is there something wrong with the setup? How could I control docker compose containers from within a container?


Docker host information:

Docker Compose version v2.1.1
Client:
 Cloud integration: v1.0.20
 Version:           20.10.10
 API version:       1.41
 Go version:        go1.16.9
 Git commit:        b485636
 Built:             Mon Oct 25 07:43:15 2021
 OS/Arch:           darwin/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.10
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.9
  Git commit:       e2f740d
  Built:            Mon Oct 25 07:41:30 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.4.11
  GitCommit:        5b46e404f6b9f661a205e28d59c982d3634148f8
 runc:
  Version:          1.0.2
  GitCommit:        v1.0.2-0-g52b36a2
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

CodePudding user response:

Compose has the notion of a project name. Compose sets a label on the container it creates with the project name, and uses this to find containers later. More visibly, the project name is also part of the default container, network, and volume names; if you docker network ls and see somename_default, that embeds the project name.

The default project name is the basename of the current directory, but you can set a COMPOSE_PROJECT_NAME environment variable to override it. In your example, you're running /tmp/docker-compose.yml so the default project name is tmp, but that doesn't match what you've run from the host. You can manually set this environment variable when you launch the container:

docker run --rm -it \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /current_directory/:/tmp/ \
  -e COMPOSE_PROJECT_NAME=$(basename $(pwd)) \  # <-- add this
  docker/compose -f /tmp/docker-compose.yml ps

There is equivalently a docker-compose -p option, though you need to consistently remember to use it on every invocation.

docker run --rm -it \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /current_directory/:/tmp/ \
  docker/compose \
  -f /tmp/docker-compose.yml \
  -p $(basename $(pwd)) \       # <-- instead of -e COMPOSE_PROJECT_NAME
  ps
  • Related