When your development workflow depends on OpenVPN but your host machine is forced to run a corporate VPN, things can get complicated fast. Host-level VPN software often takes over routing rules, intercepts private networks, and breaks access to remote development services, even when your OpenVPN configuration is correct.
Our team faced this exact issue. Instead of fighting with the host VPN client, we chose a better alternative: we moved the OpenVPN connection inside our Docker development containers.
This article explains the problem, the reasoning, and the complete solution, step by step.
Modern corporate VPN clients often enforce strict security policies. They often:
Our development environment relied on OpenVPN to reach remote services. The OpenVPN client could still “connect”, but the host VPN silently hijacked traffic and routed it through its own tunnel instead. OpenVPN showed as connected, but the dev environment was unreachable.
Here’s the key insight: Docker containers run in their own network namespaces. That means host VPN routing rules don’t affect container routing.
By moving OpenVPN into the container:
This technique cleanly separates host networking (corporate VPN) from development networking (OpenVPN inside Docker), creating a stable and conflict-free environment.
First, ensure the package is available in your Dockerfile:
RUN apt-get install -yqq ... openvpn
RUN mkdir -p /opt/openvpn && chown -R user:user /opt/openvpn
OpenVPN needs privileges to create tun devices. In your docker-compose.yml:
privileged: true
cap_add:
- NET_ADMIN
Developers store VPN files under .dockerdev/ovpn/:
volumes:
- ./ovpn:/opt/openvpn
Make sure these files are ignored by Git.
*.ovpn
OPEN_VPN_CONFIG=/opt/openvpn/$CUSTOMER_NETWORK.ovpn
if [ -f "$OPEN_VPN_CONFIG" ]; then
echo "Connecting with VPN"
sudo openvpn --daemon --log-append /var/log/openvpn/openvpn.log --config $OPEN_VPN_CONFIG
fi
exec "$@"
The container checks the selected network and launches OpenVPN automatically.
CUSTOMER_NETWORK: dev-eu-west-3
The value must match an existing .ovpn file:
dev-eu-west-3.ovpn
Once the infrastructure is in place, the developer workflow is simple:
bin/dockerdev setup
Place them in .dockerdev/ovpn/dev-eu-west-3.ovpn
cd .dockerdev
cp compose.override.yml.sample compose.override.yml
Edit as needed setting the CUSTOMER_NETWORK environment variable to the right VPN name.
bin/dockerdev start server
If an OpenVPN profile exists, the VPN starts inside the container automatically.
Running OpenVPN inside Docker gives you:
✅ No more routing conflicts.
✅ Clean separation between host and development networks.
✅ Predictable and isolated development routing.
✅ Zero host OS changes.
✅ Faster onboarding for developers.
✅ A fully reproducible environment.
✅ Reliable access to cloud services behind OpenVPN.
This architecture dramatically improved our development workflow, and it’s a pattern any remote-friendly or cloud-based team can benefit from.