Even Smaller Docker OpenVPN Container
After minimizing openvpn shown in the Minimal docker openvpn container post I finally got round to going one step further and using buildroot.
Docker shows the image size is now down to 5.598 MB and it only uses ~3MB or ram when running.
Here's how.
First you need a linux machine with the buildroot repo cloned. You'll need the development tools for your platform as well as a few other packages. For a freshly installed Centos 7 system
yum groupinstall "Development Tools" yum install wget ncurses-devel bc
A couple of things are required before you can compile your root filesystem
run make menuconfig
to configure the system and
- Tell buildroot to compile for 64 bits target.
Go to the “target architecture” menu, and change from i386 to x86_64.
- Disable uClibc utilities
Go to "toolchain" and deselect "Compile and install uClibc utilities"
- Select required packages.
Go to "target packages" -> "networking applications" and select both openvpn and iptables
- Prep image for docker
Docker needs /etc/resolv.conf and /sbin/init to be files not links. We also need a start script for openvpn in the filesystem. The cleanest way to achieve this is to use a post build script. Create the following dir/files in the buildroot root:
docker/openvpn/post.sh
#!/bin/bash # lets be cautious if [ "$TARGET_DIR" = "" ]; then echo "POST: TARGET_DIR not set" exit 1 fi rm $TARGET_DIR/etc/resolv.conf $TARGET_DIR/sbin/init touch $TARGET_DIR/etc/resolv.conf $TARGET_DIR/sbin/init cp docker/openvpn/init.sh $TARGET_DIR/init.sh chmod 750 $TARGET_DIR/init.sh
docker/openvpn/init.sh
#!/bin/sh mkdir -p /dev/net mknod /dev/net/tun c 10 200 IP=$(grep '^server .*$' /etc/openvpn/server.conf | awk '{print $2}') iptables -t nat -A POSTROUTING -s ${IP}/24 -o eth0 -j MASQUERADE exec openvpn --cd /etc/openvpn --config /etc/openvpn/server.conf --script-security 2
Go to "system configuration", select "Custom scripts to run before creating filesystem images" and enter docker/openvpn/post.sh, making sure this file is executable.
All other options can be left at default.
Exit the menuconfig system and save your new config
We're now ready to build, run make
and go get a cup of coffee or two.
Once complete the build will have produced a tarfile of the root filesystem at output/images/rootfs.tar. Import this into docker and run to make sure it's configured correctly.
docker import - <container name> < output/images/rootfs.tar docker run -t -i <container name> /bin/sh
At this point we should be ready to go. Assuming opevpn config is in /data/openvpn, the container can either be started with
docker run -d -p 1194:1194 -v /data/openvpn:/etc/openvpn --cap-add=NET_ADMIN <containername> /init.sh
or we can update the container with the CMD required to start it
# dockerfile to update image FROM <containername> EXPOSE 1194 CMD["/init.sh"]
You can pull this image direct from docker with docker pull aussieade/tinyvpn
but where's the fun in that ;-)