OpenVPN Docker Sidecar
This example shows how to run a sidecar OpenVPN container that connects to an OpenVPN server, allowing other containers to use the VPN connection. The host need not have OpenVPN installed, and the sidecar container handles all VPN operations. The OpenVPN tunnel is exclusively available only to the other containers in this docker compose that uses network_mode: "service:openvpn" setting and not to the host or any other containers.
Note that in this setup, the app container's network stack is merged with the openvpn container's network stack. This is similar to network_mode: host, where the container's network stack is merged with the docker host. The /etc/resolv.conf is shared between both the app and openvpn containers, allowing the app container to resolve DNS queries through the VPN.
If OpenVPN server is pushing custom DNS servers to the client, then openvpn/up.sh and openvpn/down.sh scripts are required to modify /etc/resolv.conf in the openvpn container.
Filename: docker-compose.yml
# Filename: docker-compose.yml
# Multi-container Docker application using OpenVPN sidecar to provide VPN
# access to other containers.
name: openvpn-app-example-com
services:
app:
# Run dummy alpine container in place of actual workload
image: alpine
restart: always
container_name: app.example.com
network_mode: "service:openvpn"
command: ["sleep", "infinity"]
depends_on:
- openvpn
openvpn:
build: .
restart: always
devices:
- /dev/net/tun
cap_add:
- NET_ADMIN
- MKNOD
volumes:
- ./openvpn/oasis-oci-hyd.ovpn:/etc/openvpn/client.ovpn
- ./openvpn/up.sh:/etc/openvpn/up.sh:ro
- ./openvpn/down.sh:/etc/openvpn/down.sh:roFilename: Dockerfile
FROM alpine:3.21
RUN apk add --no-cache openvpn
ENTRYPOINT ["/usr/sbin/openvpn", "--config", "/etc/openvpn/client.ovpn"]Filename: openvpn/up.sh
#!/bin/sh
# Filename: openvpn/up.sh
# Set DNS inside the docker container *after* openvpn connects
# chmod 755 openvpn/up.sh
# In openvpn.conf, ensure to set the following:
# script-security 2
# up /etc/openvpn/up.sh
# down /etc/openvpn/down.sh
cat /etc/resolv.conf > /etc/resolv.conf.docker
# Manually set the OpenVPN DNS servers to be used.
# Reading OpenVPN DNS values is not trivial, so setting the DNS IPs manually.
cat > /etc/resolv.conf << EOF
nameserver 10.200.11.21
nameserver 10.200.12.21
EOFFilename: openvpn/down.sh
#!/bin/sh
# Filename: openvpn/down.sh
# Restore original docker DNS settings
# chmod 755 openvpn/down.sh
# In openvpn.conf, ensure to set the following:
# script-security 2
# up /etc/openvpn/up.sh
# down /etc/openvpn/down.sh
cat /etc/resolv.conf.docker > /etc/resolv.confOpenVPN Inside Proxmox LXC
Proxmox LXC containers require specific configurations to allow OpenVPN to run correctly. The following settings should be manually added to the LXC container configuration file (e.g., /etc/pve/lxc/<container_id>.conf):
lxc.cgroup.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file