pipes

What is Pipework?

Pipework is a script that adds an IP to LXC containers, taking as arguments the host interface (normally a bridge device), the name of the guest to which the interface is added, and an IP address. The guest name can be an LXC cgroup, a Docker instance ID, or a Docker name. The IP address parameter can be a bridge or an IP address with an optional netmask and gateway parameter.

Why should you use it?

Normally with Docker, the IP address given to a container is randomly generated and not publically accessible. If you then want to make a container externally accessible, you set up networking in the host system and “expose” or map the port from the container to the host system. This is great in theory, but suppose you want three separate Web servers all listening on 80. In this case, the Docker host needs three separate IPs configured, and Docker needs to map the container to the correct IP.

With Pipework, you can assign an IP on the network, and any ports exposed in the Dockerfile are available from that IP address. This allows setting up Docker instances much as you would a normal virtual machine, where the Docker instance can have a directly accessible static IP. Also, by setting the gateway, you can enforce all traffic exits on the Docker instance through that IP and create EGRESS firewall rules for that Docker instance. By contrast, when mapping ports to the host, it’s impossible to know the IP of the instance traffic will originate from ahead of time.

Installing Pipework

Pipework is a single shell script and can be installed using the following command:

sudo bash -c "curl https://raw.githubusercontent.com/jpetazzo/pipework/master/pipework > /usr/local/bin/pipework"

The only required dependencies are Bash and iproute2 utilities. Docker integration will require Docker being installed, and the DHCP option requires a DHCP client being available. You’ll also need to set up your Ethernet interface in Linux as a bridge (not discussed here).

Using Pipework with Docker

docker logo

If you’re using named Docker instances, then adding the IP address 10.40.33.21 to a Docker instance bind is as simple as:

pipework br0 bind 10.40.33.21/24

If you want to route out of 10.40.33.1, change it to:

pipework br0 bind 10.40.33.21/24@10.40.33.1

If you aren’t naming your Docker containers, replace the name with the Docker instance ID (which can be found with docker ps).

Also, Pipework can execute Docker itself, as Docker returns the instance ID:

pipework br0 $(/usr/bin/docker run -d bind) 10.40.33.21/24@10.40.33.1

Automating Startup of Your Docker Instance with Pipework and systemd

systemd diagram

If your system uses systemd, it's really simple to set up Docker instances to start on boot with Pipework. Here's a simple service file:

/etc/systemd/system/docker-bind.service:

[Unit]
Description=Docker BIND DNS Server
After=docker.service
Requires=docker.service

[Service]
ExecStartPre=/usr/bin/docker kill bind
ExecStartPre=/usr/bin/docker rm bind
ExecStart=/usr/bin/docker run --name bind bind
ExecStartPost=/usr/bin/pipework br0 bind 10.40.33.21/24@10.40.33.1
ExecStop=/usr/bin/docker stop bind

[Install]
WantedBy=multi-user.target


This service can then be started manually with:

systemctl start docker-bind.service


It can also be configured to start on boot with:

systemctl enable docker-bind.service