Open NathanDeMaria opened 3 years ago
I would like to support it but with one reservation: if the devcontainer.json will be published in a repository secret will be available in the boilerplate form unlike in the Docker image. Their secrets are encoded. It is a problem with buildkit too. Other Image builders prefer to attach secrets to containers in a very tricky way, as separate artifacts, to separate them from the published code.
I don't think I'm following. If somebody wants devcontainer.json
published to the repository, they can use the src
argument to point to a file containing the secret, and then include the secret file in their .gitignore
. So only the name of the file containing the secret is published, not the value
I'm testing Podman 3.1 on WSL and found that the implementation of such a feature is feasible and even easy. Podman, unlike Docker supports secrets out-of-the-box with no pre-requisites like builglit or swarm. 1st, I created rsa key in the regular way in my Windows Home directory: _ls /mnt/c/Users/Pavel/idrsa /mnt/c/Users/Pavel/idrsa Then I created The myidRsa artifact using _podman secret create MyidRsa /mnt/c/Users/Pavel/idrsa Then I run UBI ubuntu image passing the secret to the container podman run -it --secret MyidRsa ubuntu and finally, I got my secret available inside the container: ls /run/secrets MyidRsa The secret is stored as podman secret inspect MyidRsa [ { "ID": "d6079304f365d8a66913df6a5", "CreatedAt": "2021-04-22T09:33:09.1095971+03:00", "UpdatedAt": "2021-04-22T09:33:09.1095971+03:00", "Spec": { "Name": "MyidRsa", "Driver": { "Name": "file", "Options": null } } } ] using file driver. Podman's secret implementation is not fully secure unless its storage root is not bitlocked but very convenient. On another hand my original secret file doesn't move to any place and not published to the git repository because it is not inside my development workspace. It will be a great, very useful feature!
I don't think I'm following. If somebody wants
devcontainer.json
published to the repository, they can use thesrc
argument to point to a file containing the secret, and then include the secret file in their.gitignore
. So only the name of the file containing the secret is published, not the value
@NathanDeMaria Could you give an example of what this might look like?
I can give an example:
Eg, for a project using poetry
:
# run the tool and generate a temporary `.netrc` style file
docker build . --secret id=netrc,src=$$NETRC
# In Dockerfile..
RUN --mount=type=secret,id=netrc,dst=/app/.netrc NETRC=/app/.netrc poetry install --no-interaction
This is also how we inject creds in our CI pipeline, so we're not looking to change our build process to accommodate editor nuances, as this way leaves no trace of the credentials in the docker image (as opposed to passing them as ARG
or environment variables.)
We can already generate the temporary credentials file and remove it with the initializeCommand
and postCreateCommand
options, but currently no way to enable buildkit and pass secrets, so for now we can only create images outside of vscode.
To be honest, a more flexible approach would not be to add build.secrets
, but to allow us to specify buildCommand
, buildArgs
and buildEnv
. Otherwise, you're constantly chasing whatever features are added to docker.
I can give an example:
- Our private python packages are stored in Artifactory, and we use Artifactory as the sole package resource
- As developers, we run a custom tool to authenticate and generate temporary oauth tokens that allow us to access them that we store in a temporary file.
- We use buildkit secrets to inject those credentials in to the docker build so that we can access Artifactory
Eg, for a project using
poetry
:# run the tool and generate a temporary `.netrc` style file docker build . --secret id=netrc,src=$$NETRC # In Dockerfile.. RUN --mount=type=secret,id=netrc,dst=/app/.netrc NETRC=/app/.netrc poetry install --no-interaction
This is also how we inject creds in our CI pipeline, so we're not looking to change our build process to accommodate editor nuances, as this way leaves no trace of the credentials in the docker image (as opposed to passing them as
ARG
or environment variables.)We can already generate the temporary credentials file and remove it with the
initializeCommand
andpostCreateCommand
options, but currently no way to enable buildkit and pass secrets, so for now we can only create images outside of vscode.To be honest, a more flexible approach would not be to add
build.secrets
, but to allow us to specifybuildCommand
,buildArgs
andbuildEnv
. Otherwise, you're constantly chasing whatever features are added to docker.
I am trying to achieve something similar in one of my use cases of making codespaces usable for my team.
My use case is to have a built container with the packages being stored in Artifactory and tokens are to be set in the .condarc
for authentication.
For the same I am using Dockerfile to prepare a conda environment which will have these packages, but having trouble with environment variables to authenticate to the Artifactory
Can you please give an idea of if you are generating the tokens on fly in the initializeCommand
or are you fetching it from somewhere?
I tried adding secrets in codespaces secret in my user account. They are available in terminal but if I pass them as docker args, they arent available. Any thoughts would be appreciated!
This is slightly orthogonal to the actual problem here, but we are generating the tokens on the fly in initializeCommand
.
We have a custom in house tool that authenticates to JFrog via SAML. The tool prompts users on the command line for username/password/2fa that allows them to authenticate to an on-prem Shibboleth Identity Provider. Once authenticated to JFrog, it uses their token service to generate a temporary access token.
In vscode, I believe that prompt appears in the console.
We are using containers, we aren't using codespaces, if that makes a difference. I'm not sure that it would, initializeCommand
runs on the local machine, not the remote.
did anybody manage to get --secrets
working?
I can give an example:
* Our private python packages are stored in Artifactory, and we use Artifactory as the sole package resource * As developers, we run a custom tool to authenticate and generate temporary oauth tokens that allow us to access them that we store in a temporary file. * We use buildkit secrets to inject those credentials in to the docker build so that we can access Artifactory
Eg, for a project using
poetry
:# run the tool and generate a temporary `.netrc` style file docker build . --secret id=netrc,src=$$NETRC # In Dockerfile.. RUN --mount=type=secret,id=netrc,dst=/app/.netrc NETRC=/app/.netrc poetry install --no-interaction
This is also how we inject creds in our CI pipeline, so we're not looking to change our build process to accommodate editor nuances, as this way leaves no trace of the credentials in the docker image (as opposed to passing them as
ARG
or environment variables.)We can already generate the temporary credentials file and remove it with the
initializeCommand
andpostCreateCommand
options, but currently no way to enable buildkit and pass secrets, so for now we can only create images outside of vscode.To be honest, a more flexible approach would not be to add
build.secrets
, but to allow us to specifybuildCommand
,buildArgs
andbuildEnv
. Otherwise, you're constantly chasing whatever features are added to docker.
We have the exact same workflow with Gitlab and need a solution.
We're in the same situation, we use buildkit to inject secrets for private Python packages, having a different build process just for running containers locally isn't ideal.
Would be great to have working support for --secrets
. Dev containers are amazing otherwise. Added support for custom build args would be sufficient in my case. Thanks.
@blacktaxi I ended up using "runArgs" in the devcontainer.json file, it seems to be working well so far.
https://code.visualstudio.com/docs/remote/devcontainerjson-reference
That's great, thanks for sharing @DougPlumley. I wonder if it's possible to do the same while building the dev container image? I'm trying to install packages from local repository as part of the image.
@blacktaxi based on my limited experience with the devcontainer and how I'm using it I felt comfortable including my secrets in the environment since I'm not building to publish the image and I'm only using the devcontainter locally.
I have a separate Dockerfile for building the image we'd use in production.
So for the Python development I'm doing for example I'm providing a PIP_EXTRA_INDEX_URL environment variable with the necessary details to install from a local package index.
@DougPlumley Just a small warning, offtopic: be very careful with PIP_EXTRA_INDEX_URL
. You don't have control over package names in global PyPI. If you privately host my-package-xyz
and global PyPI also has a package my-package-xyz
, pip can't tell the difference between them. pip install my-package-xyz
will install the version with the highest number, but you have no idea where it came from.
@DougPlumley Just a small warning, offtopic: be very careful with
PIP_EXTRA_INDEX_URL
. You don't have control over package names in global PyPI. If you privately hostmy-package-xyz
and global PyPI also has a packagemy-package-xyz
, pip can't tell the difference between them.pip install my-package-xyz
will install the version with the highest number, but you have no idea where it came from.
Appreciate the warning @maciek16180! I'll look into alternative methods as well.
i was happy to find this thread, and disappointed that it's still an open issue. anybody managed to find a workaround?
i was happy to find this thread, and disappointed that it's still an open issue. anybody managed to find a workaround?
I opted to use "runArgs": ["--env-file=.env"] in my .devcontainer.json configuration, that's where I'm mounting the secrets into the running container (not during build), I then trigger a shell script post create with "postCreateCommand": "/bin/bash -c .devcontainer/postCreateCommand.sh" that's installing my remaining dependencies which need the secrets to access private repositories.
The workaround we've been using is:
--secret
s) as part of initializeCommand
in the devcontainer.json
, building to some hard-coded image name
./generate_token.sh && docker build ...
devcontainer.json
's image
property to that hard-coded image nameIt mostly feels the same to a user as the ideal workflow, the only real difference we've noticed is the error is displayed a bit differently if the image build fails
The workaround we've been using is:
Include the full build command (including
--secret
s) as part ofinitializeCommand
in thedevcontainer.json
, building to some hard-coded image name
- Our secret is getting an auth token for AWS CodeBuild, so the command is something like
./generate_token.sh && docker build ...
- Point the
devcontainer.json
'simage
property to that hard-coded image nameIt mostly feels the same to a user as the ideal workflow, the only real difference we've noticed is the error is displayed a bit differently if the image build fails
Thank you @NathanDeMaria, after reading your comment here I took the same approach (although we're not using initializeCommand
because our developer workflow means that in our case the image should already exist anyway).
Specifying image
works great, though I agree that build.secrets
should be supported.
Would really like --secrets to be able to be implemented. Or addition docker build command line arguments in a json/ dict style arguments inside the devcontainer.json file. Currently just using the command line outside and keeping the --secret layer early in the build so most changes allow the docker image to build once and the later layers changes can be done natively from vs code extension. This won't work as a solution for codespaces but good for local development environment. Posted on github for anyone that wants it.
I found another nice workaround: use a docker-compose.yml
file and make use of the build.secrets
feature as documented here. Reference the docker-compose.yml
file in your devcontainer.json
file as documented here.
Note: VS Code uses docker-compose ...
(not docker compose ...
). At least on macOS, docker-compose ...
does not support build-secrets, but docker compose
does. Simply open the Docker Desktop settings and check the "Use Docker Compose V2" checkbox to fix this.
This thread has been stale for a while, but thought I would share another solution that I landed on after trying a few suggested in this thread. Maybe help the next person out.
The build.options
field in the devcontainer.json can be leveraged to pass a --secret
flag to the docker build
command that the dev container build calls. The secret can then be mounted to a run command in the dockerfile.
devcontainer.json:
{
"build": {
"options": [
"--secret=id=credentials,src=/home/user/.config/credentials.json"
],
}
}
Dockerfile:
RUN --mount=type=secret,id=credentials,dst=/home/user/whateverdestination install_command
I'd like a way to use build secrets BuildKit's
--secret
in remote containers. Seemingly straightforward implementation: add a field forsecrets
underneathbuild
indevcontainer.json
(list of strings), and map each entry in that list to a--secret
arg whenever thedocker build
command gets createdThis is related to https://github.com/microsoft/vscode-remote-release/issues/1409, but that's not required (if users have some other way to make sure they're using BuildKit, this feature could be independently useful).