Docker socket proxy using Nginx for security.
8.6K
This is a reverse proxy for your Docker socket that allows you to control what Docker API endpoints can be accessed by Docker clients such as Portainer, Diun and Watchtower.
Using a proxy is important from a security perspective because giving direct access to your Docker socket essentially means giving root access to your host, and also could allow undesired changes to your other Docker containers and Docker environment.
This Docker image is based upon the official Nginx Alpine image with a small Python script that creates a nginx.conf file based upon environment labels you set when you run the image. By default certain read-only API commands are allowed (see below for more details), but you can adjust to suit your needs. Where access to a certain API command has been revoked, an HTTP 403 Forbidden status is returned and there is an option that allows you to include additional details in the message (see below for more details).
Run the container using a command similar to the following (Note: You may need the --privileged flag due to SELinux/AppArmor, but try it without first):
$ docker container run \
-d --privileged \
--name docker-proxy \
-e CONTAINERS=1 \
-v /var/run/docker.sock:/var/run/docker.sock \
-p 127.0.0.1:2375:2375 \
mjmccans/docker-socket-proxy
You can list running containers because we set the CONTAINERS=1 environment variable:
$ docker -H localhost:2375 container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4f828bbd0dcc mjmccans/docker-socket-proxy "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 80/tcp, 127.0.0.1:2375->2375/tcp docker-proxy
However, you cannot list images because we did not override the default IMAGES=0 environment label:
$ docker -H localhost:2375 image ls
Error response from daemon: 403 Forbidden: docker-socket-proxy is configured to not allow access to this function. To enable this function turn on the IMAGES option.
See the "examples" folder for some docker compose examples.
The container provides useful log output showing what API calls have been made, the return codes and additional details that can be helpful for configuration and debugging. You can turn on the DESCRIPTIVE_ERRORS option to get more descriptive logging and client-side messages where a request is rejected. Turning on the DESCRIPTIVE_ERRORS option creates a more complex nginx.conf file that contains more 'locations', so I recommend turning the option off once you have everything set up.
In the example below, we can see that the first call to info has been accepted (return code 200) and the call to volumes\create has been rejected (return code 403). In addition, the last part of each line shows what environment variable option was in play to create this outcome. Note that if you do not have the DESCRIPTIVE_ERRORS option enabled you will not be given a specific environment variable option where an API call is rejected.
[25/Jan/2023:15:25:12 -0500] "GET /info HTTP/1.1" 200 [Location: INFO]
[25/Jan/2023:15:25:16 -0500] "POST /volumes/create HTTP/1.1" 403 [Location: VOLUMES_CREATE (BLOCKED)]
On the client side you can also get helpful information. With the DESCRIPTIVE_ERRORS option enabled you would get the following return message on the client side:
403 Forbidden: docker-socket-proxy is configured to not allow access to this function. To enable this function turn on the VOLUMES_CREATE option.
Without the DESCRIPTIVE_ERRORS option enabled you would get a more generic return message on the client like the following:
403 Forbidden: docker-socket-proxy is configured to not allow access to this function.
Granting or revoking access to certain Docker API calls is done by setting environment variables, and the environment variables generally match the Docker API command they relate to.
To grant or revoke access set the corresponding environment variable as follows:
0 to revoke access.1 to grant access.Below is a list of all of the options and each has a link to the Docker API Specification document so you can understand what each does.
By default, the following options are set (and you can more details on each below):
DESCRIPTIVE_ERRORSEVENTSPINGVERSIONDESCRIPTIVE_ERRORS: See above for more details.This project was inspired by tecnativa/docker-socket-proxy and fluencelabs/docker-socket-proxy. Both of those projects build upon haproxy while I am more familiar (but by no means an expert) with Nginx so I have used Nginx for this project. I also wanted to include a finer level of control similar to what is included in fluencelabs' project, and also wanted to include more detailed log messages and client messages to assist with setup and debuging.
Content type
Image
Digest
sha256:5b5546553…
Size
41.1 MB
Last updated
about 2 months ago
docker pull mjmccans/docker-socket-proxy