skip to Main Content

I have two docker containers, A and B, that are spun up with docker-compose files. I want to be able to bring the container B down with the command `docker-compose -f docker-compose.B.yaml down’ from within container A.

Is this possible?

I tried to mount container B’s docker compose file and /var/run/docker.sock. But when I run the command using a sub process in python (again from within container A), I get a ‘no resource found error’.

docker:

services:
  Service A:
    image: imageA:rel_1.0.0
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock 
      - /path/to/docker-compose.B.yaml:/projectA/docker-compose.B.yaml
.
.
.


python:

#docker-compose.py
import subprocess

compose_file_path = '/projectA_directory/docker-compose.B.yaml'
command = f"docker-compose -f {compose_file_path} down"

result = subprocess.run(command, shell=True, check=True, capture_output=True, text=True)
logger.info(f"Command output: {result.stdout}")
logger.error(f"Command error: {result.stderr}")

Error:

ContainerA | ERROR | 2024-07-29T19:56:51-0600 | docker-compose.py:62 | Command error: Warning: No resource found to remove for project "projectA".

2

Answers


  1. Docker compose assigns a "project name" to your containers, which by default is based on the name of the directory that contains your compose.yaml file. That is, if have:

    myproject/
      compose.yaml
    

    And compose.yaml looks like this:

    services:
      serviceA:
        image: docker.io/alpinelinux/darkhttpd
      serviceB:
        image: docker.io/alpinelinux/darkhttpd
    

    Then when I run docker compose up from within the myproject directory:

    cd myproject
    docker compose up -d
    

    I end up with the following containers:

    CONTAINER ID   IMAGE                   COMMAND                  CREATED          STATUS          PORTS      NAMES
    8f1c8998b15f   alpinelinux/darkhttpd   "darkhttpd /var/www/…"   19 seconds ago   Up 18 seconds   8080/tcp   myproject-serviceA-1
    05c2ee47abd5   alpinelinux/darkhttpd   "darkhttpd /var/www/…"   19 seconds ago   Up 18 seconds   8080/tcp   myproject-serviceB-1
    

    Each of those containers has some labels assigned to it:

    $ docker container inspect myproject-serviceA-1 | jq '.[0].Config.Labels'
    {
      "com.docker.compose.config-hash": "d1e91247ae0afe7dc2cb0ce473930c5c59d82e5089711008808219feaf90fdfc",
      "com.docker.compose.container-number": "1",
      "com.docker.compose.depends_on": "",
      "com.docker.compose.image": "sha256:a8b7188f53f3112dbe425a0eae4074d46d47e5c08380b918ba211b6b2fb30218",
      "com.docker.compose.oneoff": "False",
      "com.docker.compose.project": "myproject",
      "com.docker.compose.project.config_files": "/home/lars/tmp/containers/myproject/compose.yaml",
      "com.docker.compose.project.working_dir": "/home/lars/tmp/containers/myproject",
      "com.docker.compose.service": "serviceA",
      "com.docker.compose.version": "2.29.1"
    }
    

    The com.docker.compose.project label is how docker compose identifies containers that belong to your current project. If you rename a directory, like this:

    cd ..
    mv myproject bobsproject
    cd bobsproject
    

    Then compose will have the wrong project name, and it won’t be able to interact with those containers:

    $ docker compose ps
    NAME      IMAGE     COMMAND   SERVICE   CREATED   STATUS    PORTS
    $ docker compose down
    

    We can set an explicit project name using the --project-name (-p) command line option:

    $ docker compose -p myproject ps
    NAME                   IMAGE                             COMMAND                  SERVICE    CREATED         STATUS         PORTS
    myproject-serviceA-1   docker.io/alpinelinux/darkhttpd   "darkhttpd /var/www/…"   serviceA   5 minutes ago   Up 5 minutes   8080/tcp
    myproject-serviceB-1   docker.io/alpinelinux/darkhttpd   "darkhttpd /var/www/…"   serviceB   5 minutes ago   Up 5 minutes   8080/tcp
    

    Or by setting the COMPOSE_PROJECT_NAME environment variable:

    $ COMPOSE_PROJECT_NAME=myproject docker compose  ps
    NAME                   IMAGE                             COMMAND                  SERVICE    CREATED         STATUS         PORTS
    myproject-serviceA-1   docker.io/alpinelinux/darkhttpd   "darkhttpd /var/www/…"   serviceA   7 minutes ago   Up 7 minutes   8080/tcp
    myproject-serviceB-1   docker.io/alpinelinux/darkhttpd   "darkhttpd /var/www/…"   serviceB   7 minutes ago   Up 7 minutes   8080/tcp
    

    In your question, it looks like you are mounting your compose project under a different directory name in the container than you are using on the host. You can solve this by either:

    • Using the same directory name inside the container,
    • Using the --project-name argument to docker compose, or
    • Setting the COMPOSE_PROJECT_NAME environment variable
    Login or Signup to reply.
  2. It’s possible.

    1. Add call.sh file to the same directory as docker-compose.yml.
    #! /bin/bash
    nsenter -t 1 -m -u -i -n /bin/bash << EOF
    ssh -q -o StrictHostKeyChecking=no -o PasswordAuthentication=no [email protected]
    
    $1
    
    EOF
    

    change 192.168.0.101 to your host ip address.
    2. Modify your docker-compose files

      Service A:
        image: imageA:rel_1.0.0
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock 
          - /path/to/docker-compose.B.yaml:/projectA/docker-compose.B.yaml
          - call.sh:/projectA/call.sh
        privileged: true
        pid: host
        ipc: host
    
    1. Execute /projectA/call.sh docker stop containerB_name in your python code.
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search