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