vscode-remote-release icon indicating copy to clipboard operation
vscode-remote-release copied to clipboard

Use local Docker config when building volumeBootstrap image

Open cortex93 opened this issue 4 years ago • 18 comments

When opening a remote container by cloning a repository, a volumeBootsrap image is built. Being behind a proxy, the builder is unable to access internet and building the image failed.

Would it be possible to pass --build-arg http_proxy=http://... somewhere in the extensions settings ?

cortex93 avatar Oct 07 '20 13:10 cortex93

Have you tried https://docs.docker.com/network/proxy/?

chrmarti avatar Oct 12 '20 08:10 chrmarti

It works to build the volumeBootstrap, but then it failed to build the devcontainer image. The docker client inside the volumeBoostrap seems to not use the host config.

cortex93 avatar Oct 13 '20 12:10 cortex93

To make it pass, I edited the volumeBootstrap.Dockerfile in ~.vscode\extensions\ms-vscode-remote.remote-containers-0.145.0\scripts and add at the end ADD ~/.docker/config.json /root/.docker/

cortex93 avatar Oct 13 '20 13:10 cortex93

As this became a feature request, I think we may clarify the requirement. What was really needed in this case is to build the devcontainer with the host docker client configuration when using the bootstrap container. I haven't test with non default registries but it may also be an issue. I expect the docker client inside the bootstrap container to be able to pull from the same registries the host is logged into.

cortex93 avatar Oct 14 '20 17:10 cortex93

For authentication to work we will need a proxy auth executable, similar to Git: https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Looking closer, i think ADD ~/.docker/config.json /root/.docker/ would not work because the config.json is not within the context folder. How did you get that to pass?

chrmarti avatar Oct 15 '20 08:10 chrmarti

For authentication to work we will need a proxy auth executable, similar to Git: https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Yes, i'm no expert but this would be needed

Looking closer, i think ADD ~/.docker/config.json /root/.docker/ would not work because the config.json is not within the context folder. How did you get that to pass?

Sorry if it was confusing, I was just giving the global idea. Actually, I put a config.json file with just the proxy part aside the volumeBoostrap.Dockerfile (i.e. in ~\.vscode\extensions\ms-vscode-remote.remote-containers-0.145.0\scripts and just do ADD config.json /root/.docker

cortex93 avatar Oct 15 '20 17:10 cortex93

I can confirm that authentication is an issue. I am trying to Clone repository in Container Volume, with a repo whose devcontainer Dockerfile contains FROM my-private-registry.com..., and it fails to access the private registry because unauthenticated.

bourquep avatar Dec 10 '20 17:12 bourquep

As above, our dev container Dockerfile contains FROM private/repo and it fails to build via Clone Repository in Container Volume because docker login is required.

mrmachine avatar Mar 03 '21 02:03 mrmachine

To run my composition I need to do some other manual work in the recovery container (create a .env file). So I thought, maybe I can just run docker login manually inside the recovery container and then Reopen in Container. Unfortunately, that did not work:

  1. The recovery and volume bootstrap containers are completely different containers, with different (but nearly identical) images.
  2. Neither the recovery or volume bootstrap containers use a VOLUME for /root/.docker that could persist the Docker config
  3. I tried adding VOLUME /root/.docker to both volumeBootstrap.Dockerfile and volumeInspect.Dockerfile, but as this is an anonymous volume it does not even persist across multiple instances of the same image, let alone from the recovery container to the volume bootstrap container.

I think this COULD work though if both the recovery and volume bootstrap containers are started with a named volume for /root/.docker. Maybe there is even no need for a separate recovery container at all. Just run the existing volume bootstrap image with a different command? The only difference is that bootstrap has compose installed and recovery has bash installed.

Of course, it would be better to just copy the directory from the host and avoid a manual step. If I understand correctly, you say this is not available in the context so ADD ~/.docker/config.json /root/.docker/config.json would not work. But you already copy .gitconfig and .ssh/known_hosts, so this must be possible somehow?

Also, I think copying ~/.docker would not work on macOS with the default Securely store Docker logins in macOS keychain setting enabled.

mrmachine avatar Mar 03 '21 23:03 mrmachine

In further testing, I have tried to add

RUN ln -s /workspaces/.docker /root/.docker

to both volumeBootstrap.Dockerfile and volumeInspect.Dockerfile, to persist Docker config across both containers.

Then, I manually run mkdir -p /workspaces/.docker and docker login in the recovery container and then Reopen in Container.

I still get the same error:

pull access denied for FOO/BAR, repository does not exist or may require 'docker login': denied: requested access to the resource is denied

Without selecting Retry, I can then exec into the still up bootstrap container and re-authenticate. It doesn't even ask for a password:

$ docker ps
CONTAINER ID   IMAGE                  COMMAND            CREATED              STATUS              PORTS     NAMES
e7059d43f035   vsc-volume-bootstrap   "sleep infinity"   About a minute ago   Up About a minute             compassionate_germain

$ docker exec -it e7059d43f035 docker login
Authenticating with existing credentials...
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

Then if I click Retry or Rebuild Container, it STILL doesn't work.

BUT, if I copy the failed command:

Command failed: docker-compose --project-name FOO -f /workspaces/FOO/docker-compose.yml -f /workspaces/FOO/.devcontainer/docker-compose.devcontainer.yml -f /tmp/docker-compose.repositoryContainer.yml up -d --build

and exec it directly on the still up bootstrap container, IT WORKS!

$ docker ps
CONTAINER ID   IMAGE                  COMMAND            CREATED          STATUS          PORTS     NAMES
eaf5f7549720   vsc-volume-bootstrap   "sleep infinity"   18 seconds ago   Up 17 seconds             crazy_galois

$ docker exec -it eaf5f7549720 docker-compose --project-name FOO -f /workspaces/FOO/docker-compose.yml -f /workspaces/FOO/.devcontainer/docker-compose.devcontainer.yml -f /tmp/docker-compose.repositoryContainer.yml up -d --build
Building django
Step 1/4 : ARG IMAGE_TAG=master
Step 2/4 : FROM "FOO/BAR:${IMAGE_TAG}"
master: Pulling from FOO/BAR
da7391352a9b: Pull complete
14428a6d4bcd: Pull complete
2c2d948710f2: Pull complete
729b5228ba00: Pull complete
311fb628a743: Pull complete
...

So, my hack to persist Docker config across the two containers does work, but NOT in the specific context when VS Code itself tries to bring up my composition. Yet running the exact same command manually via docker exec, works.

mrmachine avatar Mar 04 '21 11:03 mrmachine

I run into this today, was trying to clone a repo onto a remote container running in a network-isolated environment and got this

[1201 ms] Start: Run: docker build -f /Users/sluongngoc/.vscode/extensions/ms-vscode-remote.remote-containers-0.163.2/scripts/volumeBootstrap.Dockerfile -t vsc-volume-bootstrap /Users/sluongngoc/.vscode/extensions/ms-vscode-remote.remote-containers-0.163.2/scripts
Sending build context to Docker daemon   12.8kB
Step 1/2 : FROM alpine:3.11.2
 ---> cc0abc535e36
Step 2/2 : RUN apk add --no-cache       nodejs  git     openssh-client  docker-cli      docker-compose  ;
 ---> Running in 83fe9c443348
fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/main/x86_64/APKINDEX.tar.gz
WARNING: Ignoring http://dl-cdn.alpinelinux.org/alpine/v3.11/main/x86_64/APKINDEX.tar.gz: network error (check Internet connection and firewall)
fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/community/x86_64/APKINDEX.tar.gz
WARNING: Ignoring http://dl-cdn.alpinelinux.org/alpine/v3.11/community/x86_64/APKINDEX.tar.gz: network error (check Internet connection and firewall)
ERROR: unsatisfiable constraints:
  docker-cli (missing):
    required by: world[docker-cli]
  docker-compose (missing):
    required by: world[docker-compose]
  git (missing):
    required by: world[git]
  nodejs (missing):
    required by: world[nodejs]
  openssh-client (missing):
    required by: world[openssh-client]
The command '/bin/sh -c apk add --no-cache      nodejs  git     openssh-client  docker-cli      docker-compose  ;' returned a non-zero code: 5
[4208 ms] Command failed: docker build -f /Users/sluongngoc/.vscode/extensions/ms-vscode-remote.remote-containers-0.163.2/scripts/volumeBootstrap.Dockerfile -t vsc-volume-bootstrap /Users/sluongngoc/.vscode/extensions/ms-vscode-remote.remote-containers-0.163.2/scripts

I think I would need to be able to either customize the scripts/volumeBootstrap.Dockerfile or having the ability to specify a set of environment variable the volumeBootstrap container to run. Then I would be able to define some http_proxy with it.

sluongng avatar Mar 12 '21 15:03 sluongng

Customizing the volumeBootstrap.Dockerfile in e.g. the devcontainer.json would be very helpful for specifying a custom source for the alpine linux in a network-isolated environment (e.g. to fetch from private-url/alpine). Related: https://stackoverflow.com/q/66390636/3233827

ssc-hrep3 avatar Jun 24 '21 16:06 ssc-hrep3

@chrmarti any reasons why we can't:

  • Use a shared/named volume at /root/.docker for the bootstrap and recovery containers? So we can at least run docker login interactively from the the recovery container and have the bootstrap container also be authenticated.
  • Copy ~/.docker/ from the host, the same way we copy .gitconfig and .ssh/known_hosts (have VSCode execute docker cp ...) after starting the recovery container? So the bootstrap container can be authenticated when building the devcontainer image automatically.
  • Allow the bootstrap and/or recovery images (and shared/named volumes) be configured in devcontainer.json? So we can install additional packages that might be required in the recovery container.

mrmachine avatar Jul 08 '21 12:07 mrmachine

Copying ~/.docker sounds like it might give us a solution that works without the user having to do anything.

chrmarti avatar Jul 09 '21 07:07 chrmarti

That would be ideal. I think will not work on macOS with the default Securely store Docker logins in macOS keychain setting enabled (no credentials in ~/.docker to copy, in that case). However, that setting is easily disabled.

Can we use the same method for this, that is used for .gitconfig and ~/.ssh/known_hosts?

mrmachine avatar Jul 09 '21 11:07 mrmachine

Any news on this one? :-)

paulfelton avatar Aug 10 '21 12:08 paulfelton

Still waiting for this and with each new version of remote-containers I have to adapt the dockerfile again....

Would it maybe be possible to just add a user-config which is put into the dockerfile (after the FROM line) - so that we can put our always same solution to fix certificates in there?

resried avatar Apr 20 '22 09:04 resried

Hello, same situation here. We use a private registry and we have to pull the image manually before running the devcontainer.

vincent-vollaro-rd avatar Aug 05 '22 09:08 vincent-vollaro-rd

Also having issues with this for similar reasons as above, security and credentials that need to be provided to private repos.

david-dumke avatar Aug 31 '22 17:08 david-dumke

Hi, any updates on this? or some workaround?

ybhaw avatar Nov 07 '22 06:11 ybhaw

Hi, any updates on this? or some workaround?

Hello, the only workaround I know is to pull your image before from an external terminal.

vincent-vollaro-rd avatar Nov 07 '22 09:11 vincent-vollaro-rd

If your problem are CA-Certs, then open the bootstrap-Dockerfile (by now both in the extensions and the tmp one it tells you when starting) and add after the "FROM" the download of your CA-Certs.

With us we have to add the following:

RUN if ! [ -d /etc/ssl/certs ]; then mkdir -p /etc/ssl/certs; fi; \ HTTPS_PROXY="" HTTP_PROXY="" http_proxy="" https_proxy="" \ wget --no-check-certificate <<URL-TO-CA-CERTIFICATE>> -P /etc/ssl/certs/ ; \ update-ca-certificates

resried avatar Nov 07 '22 09:11 resried