Docker VPN and Proxy Containers
Setting up a VPN in a Docker container is very useful. You can utilise it in various ways without tunneling your entire network traffic through the VPN.
I’m currently using ProtonVPN and Protonwire as the container. It wouldn’t be too difficult to roll your own container if the VPN has CLI software (or OpenVPN or WireGuard config).
My Docker compose starts with:
services:
protonvpn:
container_name: protonvpn
image: ghcr.io/tprasadtp/protonwire:latest
networks:
# Docker network to provide VPN access
- vpn
ports:
# Expose port of the proxy container
- "1080:1080/tcp"
The vpn
network is an external overlay network referenced in the config:
networks:
vpn:
external: true
And created like so:
docker network create -d overlay --attachable vpn
A bridge
network can work if the containers are on a single machine. An overlay
network allows docker containers on other machines to connect (via docker swarm mode).
Containers on the same bridge or overlay network can add:
network_mode: "container:protonvpn"
This forces the container to use the VPN for internet access.
Using the VPN is not limited to other containers.
In the same docker-compose.yml
config I added a proxy service:
socks5:
image: serjs/go-socks5-proxy
container_name: socks5
environment:
- PROXY_PORT=1080
depends_on:
- protonvpn
network_mode: "service:protonvpn"
Because network_mode
is set to the VPN container the proxy port is not exposed here but on the vpn container. The proxy container allows VPN access from outside Docker by apps on the local system or network.
Proxy usage examples:
Command Line
Many command line apps like curl
allow you to specify a proxy option:
curl --proxy socks5://127.0.0.1:1080 https://icanhazip.com/
They may also respect the https_proxy
environment variable:
https_proxy=socks5://127.0.0.1:1080 curl https://icanhazip.com/
JavaScript / Deno
Deno has an unstable API that allows you to proxy fetch requests:
const client = Deno.createHttpClient({
proxy: {
url: `socks5://127.0.0.1:1080`
}
});
const response = await fetch(`https://icanhazip.com/`, {client});
console.log(await response.text());
Firefox Tabs
Firefox Multi-Account Containers is an official plugin by Mozilla. The plugin allows you to create sessions where local storage like cookies are separated. You can also configured these sessions to use a HTTP proxy.

This set up means that browsing the web using a VPN is as simple as opening a new tab. You could have multiple tabs open using multiple VPNs whilst others use non.
Why?
For one, there’s the obvious questionable content like downloading cars and seeding linux ISOs. It’s also useful to test/hammer APIs when you’re too lazy to read the documentation. Or you have a crazy idea like transfering files via web push notifications.
If you value your privacy and data at all you’re probably aware of how insidious tracking and fingerprinting is across the web. I use a VPN to watch YouTube, for example.
I’m not going to promote one particular VPN but just warn that free/cheap should not be an attractive proposition for VPN services.
DNS
Bear in mind that DNS queries may not be proxied using this set up. I have a separate and rather complicated set up to handle DNS (I should blog about that some day…). At the very least configure your router with an upstream DNS service like Quad9.
Have suggestions to improve this set up? @dbushell!