I am creating my first devcontainer on Visual Studio Code. I want the locally cloned repo on the host machine to be both available at build time (I need the Conan-related files conanfile.py
and profiles to be available installing dependencies in the image) and then run-time (for compiling/running/debugging code etc).
The devcontainer.json
:
{
"name": "C++",
"workspaceMount": "source=${localWorkspaceFolder},target=/app,type=bind",
"workspaceFolder": "/app",
"build": {
"dockerfile": "Dockerfile"
},
"features": {},
"customizations": {
"vscode": {
"settings": {},
"extensions": [
"streetsidesoftware.code-spell-checker"
]
}
}
}
Dockerfile
:
FROM alpine:3.17.0 AS build
WORKDIR /app
RUN apk update && \
apk add --no-cache \
build-base=0.5-r3 \
cmake=3.24.4-r0 \
python3=3.10.13-r0 \
py3-pip=22.3.1-r1
RUN pip install conan==1.61.0
RUN conan install conanfile.py
The files are not found during the build stage: ERROR: Conanfile not found at /app/conanfile.py
However, when I comment out the conan install
part, the image is built properly and I can see the files with a ls
.
I think I misunderstand the default mounting of devcontainers and how to mount files properly at build stage.
To build the container image vscode
basically just executes a docker build
with the specified Dockerfile
.
The workspaceMount
and workspaceFolder
options have no effect on the build but are only used when creating and running the dev container from the image.
So if you need some files from your source at build time you first need to COPY
them into the image, e.g.:
# ...
COPY conanfile.py /app/
RUN conan install conanfile.py
If you don't want to store the copied file(s) in the image you could use RUN --mount=type=bind
:
# ...
# bind mount the source to /app/
# note that source=/ refers to the root of the context folder, i.e., our workspaceFolder
RUN --mount=type=bind,source=/,target=/app/ conan install conanfile.py
But these both would only work correctly if the command (conan install conanfile.py
) does not modify the contents of /app/
(e.g. installing dependencies etc. into it) because with the first approach those changes would be overriden with the contents of your workspace folder at run-time when it is bind-mounted into the container.
And with the second approach building your image would require to modify the contents of the bind-mounted workspace folder, which has a whole lot of other pitfalls.
In such a case you probably should rather use onCreateCommand
, updateContentCommand
, postCreateCommand
or postStartCommand
to run the command at run-time only:
{
"name": "C++",
"workspaceMount": "source=${localWorkspaceFolder},target=/app,type=bind",
"workspaceFolder": "/app",
"build": {
"dockerfile": "Dockerfile"
},
"onCreateCommand": "conan install conanfile.py",
"features": {},
"customizations": {
"vscode": {
"settings": {},
"extensions": [
"streetsidesoftware.code-spell-checker"
]
}
}
}