devcontainer/cli with docker compose is always reusing existing container
I started integrate devcontainer/cli into Jenkins and referenced the CI-Example.
below is reproduce steps (Update: the below is not reproduced when not using dockerCompose):
my .devcontainer :
{
"name": "ms-1-ms",
"dockerComposeFile": "docker-compose.yml",
"service": "dev-container",
"workspaceFolder": "/workspace/ms-1",
}
my compose :
services:
dev-container:
image: "mcr.microsoft.com/devcontainers/base:ubuntu"
command: sleep infinity
volumes:
- ../..:/workspace
when i use : devcontainer up --workspace-folder . --id-label unique=id11
i get
[0 ms] @devcontainers/cli 0.58.0. Node.js v16.18.1. darwin 23.3.0 arm64.
[388 ms] Start: Run: docker-compose -f /Users/avishayhirsh/myApps/MicroService1/ms-1/.devcontainer/docker-compose.yml --profile * config
[475 ms] Start: Run: docker-compose -f /Users/avishayhirsh/myApps/MicroService1/ms-1/.devcontainer/docker-compose.yml --profile * config
[551 ms] name: devcontainer
services:
dev-container:
command:
- sleep
- infinity
image: mcr.microsoft.com/devcontainers/base:ubuntu
networks:
default: null
volumes:
- type: bind
source: /Users/avishayhirsh/myApps/MicroService1
target: /workspace
bind:
create_host_path: true
networks:
default:
name: devcontainer_default
[551 ms] Start: Run: docker inspect --type image mcr.microsoft.com/devcontainers/base:ubuntu
[611 ms] Start: Run: docker-compose --project-name ms-1_devcontainer -f /Users/avishayhirsh/myApps/MicroService1/ms-1/.devcontainer/docker-compose.yml build
[749 ms] Start: Run: docker-compose --project-name ms-1_devcontainer -f /Users/avishayhirsh/myApps/MicroService1/ms-1/.devcontainer/docker-compose.yml -f /var/folders/q9/6t3mffmn3dz_bcv3zhmkkgzh0000gq/T/devcontainercli/docker-compose/docker-compose.devcontainer.containerFeatures-1712474784059.yml up -d
[+] Running 1/2
⠹ Network ms-1_devcontainer_default Created 0.2s
✔ Container ms-1_devcontainer-dev-container-1 Started 0.2s
{"outcome":"success","containerId":"2c0721ac05bbf2eed047e58e34577e310a30dd75d6d5e6940b935cfe21c469ac","composeProjectName":"ms-1_devcontainer","remoteUser":"vscode","remoteWorkspaceFolder":"/workspace/ms-1"}
So far so good , now i want to spawn a new dev container (to simulate parallel dev containers running in the jenkins machine)
devcontainer up --workspace-folder . --id-label unique=id44242
but i get
[1 ms] @devcontainers/cli 0.58.0. Node.js v16.18.1. darwin 23.3.0 arm64.
{"outcome":"success","containerId":"2c0721ac05bbf2eed047e58e34577e310a30dd75d6d5e6940b935cfe21c469ac","composeProjectName":"ms-1_devcontainer","remoteUser":"vscode","remoteWorkspaceFolder":"/workspace/ms-1"}
So it is reusing the same container while i do not want to reuse the same container , nor to remove the existing i need to run a new dev container with the specific label ....
Maybe this is due to docker compose functionality but i would expect the devcontainer/cli to maybe generate new project name when it detects a different label or something ? because if the cli will create a unique project name in such case it would be able to spawn a new dev container instance... WDYT ? (or at least document that this is limitation of --id-label ?)
Though, using a unique compose project name will result with volumes not be shared across dev containers , so the only solution right now i think of is to drop usage of compose in CI flow , and rather generate a .devcontainer.json on the fly without compose in pipeline or to create devcontainer-ci.json that will not include compose, this way the problem is solved and also the volumes are shared.
Hi 👋
It seems like you're trying to run multiple instances of the same dev container simultaneously with different labels using the devcontainer up --workspace-folder . --id-label unique=id command. However, the second command is reusing the existing container instead of creating a new one.
The dev container CLI is designed to reuse existing containers if they match the specified configuration to avoid unnecessary container creation. When you specify the --id-label option, it's used to identify an existing container that matches the label. In your case, since the configuration is the same for both commands (same workspace folder and same .devcontainer configuration), the CLI is identifying the existing container as a match and reusing it, even though the --id-label is different.
This is working as expected according to the open spec.
One possible workaround for your scenario is to use a different workspace folder for each command. This would result in a different configuration for each command, and the CLI would create a new container for each one.
Another possible workaround, as you mentioned, is to generate a .devcontainer.json file on the fly without using Docker Compose, or to create a separate devcontainer-ci.json file that doesn't use Docker Compose. This would allow you to control the container configuration more precisely and ensure that a new container is created for each command.
@samruddhikhandale first thanks for your reply :)
The dev container CLI is designed to reuse existing containers if they match the specified configuration to avoid unnecessary container creation. When you specify the
--id-labeloption, it's used to identify an existing container that matches the label. In your case, since the configuration is the same for both commands (same workspace folder and same .devcontainer configuration), the CLI is identifying the existing container as a match and reusing it, even though the--id-labelis different.
Well this behavior is different when not using compose since it is creating a new instance of dev container due to the usage of --id-label with different value, as one would expect. but as noted it relies due to limitations of docker compose .
The dev container CLI is designed to reuse existing containers if they match the specified configuration to avoid unnecessary container creation. When you specify the --id-label option, it's used to identify an existing container that matches the label. In your case, since the configuration is the same for both commands (same workspace folder and same .devcontainer configuration), the CLI is identifying the existing container as a match and reusing it, even though the --id-label is different.
Even when duplicate cloned the repo to a different workspace and using different folder name , the devcontainer/cli somehow relates to the existing running container , it fails on port binding on port 9000 allthough i have also changed in the compose file in the cloned dup repo the ports to 9001:9001 as well
Another possible workaround, as you mentioned, is to generate a
.devcontainer.jsonfile on the fly without using Docker Compose, or to create a separatedevcontainer-ci.jsonfile that doesn't use Docker Compose. This would allow you to control the container configuration more precisely and ensure that a new container is created for each command.
Yes when not using docker compose --id-label works as one would expect , meaning it will create a new dev cotnainer instance in up command since the value is different.
having noted this fact i think it might be worth to somehow mention it in the cli help or in the documentation that --id-label will still reuse the same container when using docker compose. (it can save time for other developers as well) especially if they are integrating dev-container/cli in CI pipelines where the same workspace code is used but there is a need to isolate each instance of pipeline from one another ... so they can not use docker compose in such scenario (as can be seen even when cloned to a different folder there is a reference to the running container from a different workspace).
You could use the COMPOSE_PROJECT_NAME environment variable to set the project name (https://docs.docker.com/compose/project-name/#set-a-project-name). As you note, this will change volume names, maybe you can use external volumes where you control the entire name.
You could use the
COMPOSE_PROJECT_NAMEenvironment variable to set the project name (https://docs.docker.com/compose/project-name/#set-a-project-name). As you note, this will change volume names, maybe you can use external volumes where you control the entire name.
Thanks for your reply @chrmarti .
Yes it is possible to define as you mentioned the COMPOSE_PROJECT_NAME but still preprocessing should be done , e.g : 1] Move all volumes definitions to compose from devcontainer.json and mark them as external 2] Manually create these volumes as well 2] Since not possible to control the runServices in devcontainer.json from the CLI there is a need to mark only the dev container itself to be run in CI and not other dependencies which is relevant to dev purposes
Certianly all these problems do not arise when using simple devcontainer.json ... so what i am saying it's worth to mention all these facts when one consider to use devcontainer in CI or to think ahead of time maybe not use compose at all also for development purposes and this way the devcontainer.json will be used in both CI and in developers machines.