Skip to content

Instantly share code, notes, and snippets.

@kojiwell
Last active May 12, 2020 04:15
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save kojiwell/38c6baed3c60b7dd9f7c727edab38851 to your computer and use it in GitHub Desktop.
Save kojiwell/38c6baed3c60b7dd9f7c727edab38851 to your computer and use it in GitHub Desktop.
This is how to create a bridge between Docker containers and outside and create containers with the IP addresses you want to assign.

Docker - Create a Bridge and Shared Network

Sometimes I want to use Docker containers like regular VMs, creating a bridge on a Docker host, having containers on the same subnet with IP addresses I want to assign, and then logging into them via port 22. (No port forwarding, please.) So here's how to do it.

On this example, I use Vagrant and VirtualBox on my MacBook and create containers with IP addresses shown on the table below. Once you go through these steps, you should be able to extend the idea into your on-premises network.

Host IP Address
MacBook 192.168.33.1
host1(VirtualBox) 192.168.33.10
container1 192.168.33.11
container2 192.168.33.12
container3 192.168.33.13

Prerequisites

This example is done with these;

Creating a Vagrantfile

You may want to go with docker-machine create -d virtualbox <hostname>, but it is important to change the network Adapter Type in order to make the network bridge work. And it is easy to do that on Vagrantfile, which looks like this.

Vagrant.configure(2) do |config|
  config.vm.box = "ubuntu/trusty64"
  config.vm.hostname = "host1"
  config.vm.network "private_network", ip: "192.168.33.10"

  config.vm.provider "virtualbox" do |v|
    v.memory = "2048"
    # Change the network adapter type and promiscuous mode
    v.customize ['modifyvm', :id, '--nictype1', 'Am79C973']
    v.customize ['modifyvm', :id, '--nicpromisc1', 'allow-all']
    v.customize ['modifyvm', :id, '--nictype2', 'Am79C973']
    v.customize ['modifyvm', :id, '--nicpromisc2', 'allow-all']
  end

  # Install bridge-utils
  config.vm.provision "shell", inline: <<-SHELL
    apt-get update
    apt-get -y install bridge-utils
  SHELL
end

Creating a Docker machine

# Create a VM
$ vagrant up

# Setup the VM as your Docker machine
$ docker-machine create \
      --driver "generic" \
      --generic-ip-address 192.168.33.10 \
      --generic-ssh-user vagrant \
      --generic-ssh-key .vagrant/machines/default/virtualbox/private_key \
      --generic-ssh-port 22 \
      host1

Creating a bridge docker1 and shared network shared_nw

# Log in to the VM
$ vagrant ssh

# Delete the IP address from eth1
$ sudo ip addr del 192.168.33.10/24 dev eth1

# Create "shared_nw" with a bridge name "docker1"
$ sudo docker network create \
    --driver bridge \
    --subnet=192.168.33.0/24 \
    --gateway=192.168.33.10 \
    --opt "com.docker.network.bridge.name"="docker1" \
    shared_nw

# Add docker1 to eth1
$ sudo brctl addif docker1 eth1

Note: You may want to use docker-machine ssh host1 to log in to host1, but you need to use vagrant ssh instead, because 192.168.33.10 will be once deleted in the process.

Running Containers

Go back to your MacBook, and launch containers:

$ eval $(docker-machine env host1) # Setup the environment
$ docker run --name container1 --net shared_nw --ip 192.168.33.11 -dt ubuntu
$ docker run --name container2 --net shared_nw --ip 192.168.33.12 -dt ubuntu
$ docker run --name container3 --net shared_nw --ip 192.168.33.13 -dt ubuntu

And now you should be able to reach the container's IP addresses:

$ ping -c 3 192.168.33.11
$ ping -c 3 192.168.33.12
$ ping -c 3 192.168.33.13

Making the network setting permanent

At this point, the network bridge will be detatched from eth1 if you reboot the machine. So here are two more things to make the setting permanent.

Update /etc/network/interfaces like this:

auto eth1
iface eth1 inet manual
   pre-up ifconfig $IFACE up
   post-down ifconfig $IFACE down

And add the following command on /etc/rc.local(before exit 0):

brctl addif docker1 eth1

Cleaning up

After finishing your test, you can remove the containers and VM:

$ docker stop $(docker ps -aq) # Stop all containers
$ docker rm $(docker ps -aq) # Remove all containers
$ docker-machine rm host1 # Remove host1 from your machine list
$ vagrant destroy # Remove the VM

Where to go next

You may want to try Dockerizing an SSH daemon service.

References

The following links are really helpful to understand Docker's network, and highly recommended.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment