Cli: docker client configuration ".docker/config.json" not found if "docker build" is run with "sudo"

Created on 4 Jun 2018  路  8Comments  路  Source: docker/cli

Description

According to https://docs.docker.com/network/proxy/#configure-the-docker-client one can configure the docker client to use a proxy by default. If user1 runs docker build with sudo, the build fails because docker build looks for .docker/config.json in /root/.docker/config.json, but not in /home/user1/.docker/.config.json.

docker build uses https://github.com/moby/moby/blob/master/pkg/homedir/homedir_linux.go#L15 to get the current user id.

The steps below describe the problem with example code. As I found this issue while using docker build I created the issue for this project as I expect a workaround to be implemented in docker build.

Steps to reproduce the issue:

  1. Create Dockerfile
~~~dockerfile
FROM alpine

RUN echo echo \$HTTP_PROXY >> /bin/echo-test
RUN echo echo \$HTTPS_PROXY >> /bin/echo-test
RUN echo echo \$http_proxy >> /bin/echo-test
RUN echo echo \$https_proxy >> /bin/echo-test

RUN chmod +x /bin/echo-test

CMD /bin/echo-test
~~~
  1. Build image container

    ~
    docker build -t mytest .
    ~

  2. Create docker config at /root/.docker/config.json

    ~
    {
    "proxies": {
    "default": {
    "httpProxy": "http://10.0.50.1:3128",
    "httpsProxy": "http://10.0.50.1:3128"
    }
    }
    }
    ~

  3. Run container

    ~~~
    docker run -it --name test1 --rm mytest

    => Nothing

    ~~~

    ~~~
    sudo docker run -it --name test1 --rm mytest

    => Nothing

    ~~~

  4. Create docker config at ~/.docker/config.json

    ~
    {
    "proxies": {
    "default": {
    "httpProxy": "http://10.0.2.1:3128",
    "httpsProxy": "http://10.0.2.1:3128"
    }
    }
    }
    ~

  5. Run container

    ~~~
    docker run -it --name test1 --rm mytest

    => Nothing

    ~~~

    ~~~
    sudo docker run -it --name test1 --rm mytest

    => http://10.0.50.1:3128

    => http://10.0.50.1:3128

    => http://10.0.50.1:3128

    => http://10.0.50.1:3128

    ~~~

Describe the results you received:

See above

Describe the results you expected:

~~~
docker run -it --name test1 --rm mytest

=> http://10.0.2.15:3128

=> http://10.0.2.15:3128

=> http://10.0.2.15:3128

=> http://10.0.2.15:3128

~~~

~~~
sudo docker run -it --name test1 --rm mytest

=> http://10.0.50.1:3128

=> http://10.0.50.1:3128

=> http://10.0.50.1:3128

=> http://10.0.50.1:3128

~~~

Additional information you deem important (e.g. issue happens only occasionally):

Output of docker version:

Client:
 Version:      18.03.1-ce
 API version:  1.37
 Go version:   go1.9.5
 Git commit:   9ee9f40
 Built:        Thu Apr 26 07:20:16 2018
 OS/Arch:      linux/amd64
 Experimental: false
 Orchestrator: swarm

Server:
 Engine:
  Version:      18.03.1-ce
  API version:  1.37 (minimum version 1.12)
  Go version:   go1.9.5
  Git commit:   9ee9f40
  Built:        Thu Apr 26 07:23:58 2018
  OS/Arch:      linux/amd64
  Experimental: false

Output of docker info:

Containers: 82
 Running: 8
 Paused: 0
 Stopped: 74
Images: 769
Server Version: 18.03.1-ce
Storage Driver: overlay2
 Backing Filesystem: xfs
 Supports d_type: true
 Native Overlay Diff: true
Logging Driver: journald
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge host macvlan null overlay
 Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 773c489c9c1b21a6d78b5c538cd395416ec50f88
runc version: 4fc53a81fb7c994640722ac585fa9ca548971871
init version: 949e6fa
Security Options:
 seccomp
  Profile: default
 selinux
Kernel Version: 4.16.12-200.fc27.x86_64
Operating System: Fedora 27 (Workstation Edition)
OSType: linux
Architecture: x86_64
CPUs: 2
Total Memory: 7.789GiB
Name: hostname.example.com
ID: RK4I:5QMA:FVLF:A4PM:4P37:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
HTTP Proxy: http://localhost:3128
HTTPS Proxy: https://localhost:3128
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false

Additional environment details (AWS, VirtualBox, physical, etc.):

arebuilder aredistribution

Most helpful comment

Hi @maxmeyer, thank you for filling this issue.
I think you can solve your problem by setting the DOCKER_CONFIG environment variable:

$ export DOCKER_CONFIG=~/.docker

$ sudo docker build...

All 8 comments

Hi @maxmeyer, thank you for filling this issue.
I think you can solve your problem by setting the DOCKER_CONFIG environment variable:

$ export DOCKER_CONFIG=~/.docker

$ sudo docker build...

@silvin-lubecki Thanks a lot. I found the issue, it was my fault. docker was an alias in my setup (sudo /usr/bin/docker). Sorry!

There still seems to be a problem, I updated the issue description accordingly.

BTW: For other readers trying to use the workaround, don't forget to update your /etc/sudoers: Add Defaults env_keep += "DOCKER_CONFIG"; otherwise sudo will strip the DOCKER_CONFIG-variable from env.

I'm not quite sure what your expectation is regarding functionality. The core usage of sudo is "su do", essentially letting you run something as super user (root). Since you're running as root by design user path expansions (~/) will resolve to the root directory. sudo also root context switches before running the docker command so all docker will see is "I'm running as root" and not "I'm being run through sudo invoked by user X". The environment variable solution is perfectly valid given the context of how you're running docker.

As a side note this is a bit concerning from a principle of least privilege security perspective. In most cases running docker builds as a non-root user is sufficient enough. The example docker file you've provided doesn't appear to require anything for root privileges. If there is something which requires root permissions access you'd be better off considering user/group permission adjustments to make it available to the process (after researching whether or not users outside of root should be accessing it).

This is not a bug / issue with the docker cli, but the way things work when using sudo;

$ sh -c 'cd ~ && pwd'
/Users/sebastiaan

$ sudo sh -c 'cd ~ && pwd'
/Users/sebastiaan

$ sudo -H -i sh -c 'cd ~ && pwd'
/var/root

As a side note this is a bit concerning from a principle of least privilege security perspective. In most cases running docker builds as a non-root user is sufficient enough. The example docker file you've provided doesn't appear to require anything for root privileges. If there is something which requires root permissions access you'd be better off considering user/group permission adjustments to make it available to the process (after researching whether or not users outside of root should be accessing it).

@cwgem note that Docker uses a client-server architecture; the daemon (server) runs as root, and containers are running as root by default.

Using sudo <some docker command> will only run the Docker _CLI_ as root, but won't change anything about the _container_ that is started; using sudo (or adding the current user to the docker group) may be needed becase (by default), when running a local daemon, the Docker CLI connects to the daemon over a unix socket (/var/run/docker.sock), and permissions on that socket restrict a non-privileged user from connecting.

To run a _container_ as non-root;

  • use the USER Dockerfile instruction when building the Docker image that you start the container from
  • use the --user=<user>[:<group>] option when starting the container

As described above, this is not a bug, so I'll close this issue, but feel free to continue the conversation

@thaJeztah My concerns on least privilege were more around the docker build process in its entirety requiring root privileges. For example a maliciously crafted Dockerfile could copy root restricted files to the container with some code to upload it to a malicious server. Even with the docker service maintaining root privileges for various operations such as cgroup applications it still exposes it to the client through an API. Granted that being a service means that there is always the possibility of malicious content injection to API calls spawning a privilege escalation (though there are probably easier routes a malicious attacker with local access could take).

Running containers themselves can utilize cgroups for *NIX based hosts (iirc you can do VM isolation through a certain Hyper-V integration in Windows) so even running containers as root still enables some level of privilege isolation. Granted vulnerabilities in the underlying cgroup system could break that isolation.

For example a maliciously crafted Dockerfile could copy root restricted files to the container with some code to upload it to a malicious server.

When performing a docker build, you explicitly pass the _build context_ to the daemon; for example, the last . in the build command below indicates the path to the build context (in this case, the current directory);

docker build -t foobar .

What happens after that, is that the Docker CLI tar/gz's the specified path (current directory), and uploads that to the daemon.

The daemon will extract those files, and _only_ those files can be used in the Dockerfile, nothing outside of the files that were passed to the daemon as build-context.

This means that a malicious Dockerfile can only be harmful if the user got tricked into building the Dockerfile using a context that contains sensitive data ("put this Dockerfile in your home-directory, and run docker build .")

Was this page helpful?
0 / 5 - 0 ratings