How make openvpn work with docker
Solution (TL;DR;)
Create /etc/openvpn/fix-routes.sh
script with following contents:
#!/bin/shecho "Adding default route to $route_vpn_gateway with /0 mask..."ip route add default via $route_vpn_gatewayecho "Removing /1 routes..."ip route del 0.0.0.0/1 via $route_vpn_gatewayip route del 128.0.0.0/1 via $route_vpn_gateway
Add executable bit to the file: chmod o+x /etc/openvpn/fix-routes.sh
. Change owner of this file to root: chown root:root /etc/openvpn/fix-routes.sh
.
Add to your config following two lines:
script-security 2 route-up /etc/openvpn/fix-routes.sh
Explanation
Openvpn adds routes that for following networks: 0.0.0.0/1
and 128.0.0.0/1
(these routes cover entire IP range), and docker can't find range of IP addresses to create it's own private network.
You need to add a default route (to route everything through openvpn) and disable these two specific routes. fix-routes
script does that.
This script is called after openvpn adds its own routes. To execute scripts you'll need to set script-security
to 2
which allows execution of bash scripts from openvpn context.
Thanks
I'd like to thank author of this comment on github, also thanks to ovpn support.
You can also get docker-compose working if you define the subnet CIDR in your docker compose file:
networks: your-network: ipam: config: - subnet: 172.16.238.0/24 gateway: 172.16.238.1
Another option: create first the network with the subnet CIDR and then specify in the docker compose file that you want to use this network:
docker network create your-network --subnet 172.24.24.0/24
In your docker compose file:
networks: your-network: external: true
Based on answer from Anas El Barkani, here's a complete step-by-step example using PostgreSQL.
While VPN is not connected, create a permanent docker network:
docker network create my-network --subnet 172.24.24.0/24
In docker-compose file, specify network as external:
version: "2"
services: postgres: container_name: postgres image: postgres volumes: - ./volumes/postgres/data:/var/lib/postgresql/data environment: - POSTGRES_DB=dummy - POSTGRES_USER=user - POSTGRES_PASSWORD=123456 - POSTGRES_HOST=localhost networks: - default ports: - "127.0.0.1:5432:5432"
networks: default: external: name: my-network
That's all. Now you can enable your VPN, and start/stop container as usual:
docker-compose up -ddocker-compose down
No need to turn VPN on/off every time, or to add weird scripts as root.