Introduction

In many cases, we need a central Docker machine hosted in a machine available in our local network. But the problem is that when we create a Docker machine in the considered host, it cannot be accessible from the other machines in our local network. This is due to the fact that the recently-created Docker machine gets its IP address from the host-only adapter network which only is visible from the local host. In other words, we can only access the Docker machine from the host which contains the Docker machine. In this article, I will propose a way to make the Docker machine available for any host in the local network.

Create a Docker Machine

First, we need to create a Docker machine. From now on, we will call it “local-docker-host.” The command will be like this:

docker-machine create -d virtualbox local-docker-host

If we use docker-machine IP local-docker-host we will find that the machine will have some IP like 192.168.99.100. It is obviously clear that this IP cannot be accessible from our local network. Consequently, we should define another network for our created Docker machine. Meanwhile, in the docker-machine command line, we do not have proper switches to create a Docker machine with a birded network adapter. Therefore, the only solution will be configuring it manually from the VirtualBox (or any other hypervisor) console. Here we are describing how to build it in the VirtualBox hypervisor.

Define a New Network for The Docker Machine in Virtual Box

First of all, we should stop the local-docker-host by this command:  docker-machine stop local-docker-host 

Then open the virtual box console. From the gnome shell installed on the CentOS 7, we can find the installed virtualbox somewhere around here: Applications => System Tools => Oracle VM VirtualBox. Then follow these steps:

  1. Select the local-docker-host VM and open the Settings window.
  2. In the Network tab, you can see two adapters available for local-docker-host. One of them has NAT and the other one has the Host-only Adapter. Go to the Adapter 3 tab.
  3. Check “Enable Network Adapter.”
  4. Select Bridge Adapter for “Attached to:” .
  5. Collapse the Advanced tree node.
  6. Check Promiscuous Mode if it is necessary due to your network policy.
  7. Keep “Cable Connected” checked.

Afterward, click OK and close the VirtualBox console. Now you can start local-docker-host by this command:  docker-machine start local-docker-host , then regenerate the machine’s certificate by this command:  docker-machine regenerate-certs local-docker-host . If we re-run the command:  docker-machine ip local-docker-host , we will still see the 192.168.99.100 IP address. Instead of this command, ssh to the machine by this command:  docker-machine ssh local-docker-host . You will be connected to the Docker machine via the ssh command and then run this command:  ifconfig -a . You will see a list of networks that typically looks like this:

  1. docker0: This network is used by the Docker engine. The IP address will be something like: 172.17.0.1
  2. eth0: This network is used by the Docker machine. The IP address will be something like: 10.0.2.15
  3. eth1: This network is used by the local machine host which is only available from that host. The IP address will be something like: 192.168.99.100
  4. eth2: This network makes the local machine host available from the whole local network machines. The IP address will be something like: 192.168.161.99

Install the Generated Machine’s Public Certificate Into the Client Machine

Now, it is the time to go to the client machine where we are supposed to run Docker commands remotely. Before going to the considered machine, it is highly recommended to configure SAN (Subject Alternate Name) setting in the Docker machine host. It is necessary because the default security setting of local-docker-host machine will only allow you to access it via the local IP(192.168.99.100). To resolve this problem, go to the  $HOME/.docker/machine/machines/local-docker-host/  and edit the config.json file. Find the “ServerCertSANs” key and set the IP address you are supposed to connect remotely with that. In this case, it will look like this:

...

"ServerCertSANs": [
                "192.168.161.99"
            ],

...

Save the file and restart local-docker-host machine by this command:  docker-machine restart local-docker-host . Then run this command:  docker-machine env local-docker-host.  You will see the below result in the output console:

export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.100:2376"
export DOCKER_CERT_PATH="/root/.docker/machine/machines/local-docker-host"
export DOCKER_MACHINE_NAME="local-docker-host"
# Run this command to configure your shell:
# eval $(docker-machine env local-docker-host)

These variables should be set in your client machine where the Docker client tool is installed. In the second line, you should replace 192.168.99.100 with 192.168.161.99. In addition, in the third line, we should indicate the client machine certificate path, which can be somewhere like this: $HOME/local-docker-host/certs/.

Now go to the $HOME/.docker/machine/machines/local-docker-host/ in the local-docker-host machine and copy the following three files to the client machine path:

  1. ca.pem
  2. key.pem
  3. cert.pem

The client machine path should be: $HOME/local-docker-host/certs/ based on the above export commands.

Run docker-maven-plugin to Deploy Your Project in The Remote Docker Machine

There is a convenient Maven plugin called docker-maven-plugin located in io.fabric8 that we can deploy our project to a Docker host. The Maven configuration can be something like this:

...
   <profiles>
       <profile>
           <id>docker</id>
           <build>
               <plugins>
                   <plugin>
                       <groupId>io.fabric8</groupId>
                       <artifactId>docker-maven-plugin</artifactId>
                       <version>0.30.0</version>
                       <configuration>
                           <dockerHost>tcp://192.168.161.99:2376</dockerHost>(1)
                           <certPath>~/local-docker-host/certs/</certPath>(2)
                           <skipPush>true</skipPush>
                           <images>
                               <image>
                                   <alias>TestProject</alias>
                                   <name>local/testproject:1.0.0</name>(3)
                                   <build>
                                       <from>jboss/wildfly:latest</from>(4)
                                       <assembly>
                                           <descriptor>assembly.xml</descriptor>(5)
                                           <basedir>/opt/jboss/wildfly-14.0.0/standalone</basedir>
                                           <user>jboss:jboss:jboss</user>
                                       </assembly>
                                       <ports>
                                           <port>8443</port>
                                       </ports>
                                   </build>

                                   <run>
                                       <ports>
                                           <port>8443:8443</port>
                                       </ports>
                                       <log>
                                           <prefix>JB</prefix>
                                           <date>none</date>
                                           <color>cyan</color>
                                       </log>
                                   </run>
                               </image>
                           </images>
                       </configuration>
                       <dependencies>
                           <dependency>
                               <groupId>org.apache.maven.shared</groupId>
                               <artifactId>maven-shared-utils</artifactId>
                               <version>3.2.1</version>
                           </dependency>
                       </dependencies>
                       <executions>
                           <execution>
                               <id>docker:build</id>(6)
                               <phase>package</phase>
                               <goals>
                                   <goal>build</goal>
                               </goals>
                           </execution>
                           <execution>
                               <id>docker:push</id>(7)
                               <phase>install</phase>
                               <goals>
                                   <goal>push</goal>
                               </goals>
                           </execution>
                       </executions>
                   </plugin>
               </plugins>
           </build>
       </profile>

   </profiles>
...

The complementary descriptions of these lines are presented here:

(1): This should be the local-docker-host machine’s IP address.

(2): This should be the certificate’s path containing the three files: ca.pem, key.pem, cert.pem.

(3): This is your project Docker image name and tag.

(4): This is the base image which your project image will be built from that.

(5): The assembly.xml file should be created under your project path somewhere like: rootproject/src/main/docker/assembly.xml. The file should be like this:

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
    <id>javaee7-docker-maven</id>
    <dependencySets>
        <dependencySet>
            <includes>
                <include>com.test.testproject:TestProject</include>
            </includes>
            <outputDirectory>/deployments</outputDirectory>
            <outputFileNameMapping>TestProject.war</outputFileNameMapping>
        </dependencySet>
    </dependencySets>
</assembly>

(6): In the package phase we are supposed to build our Docker image.

(7): In the install phase we are supposed to push our built Docker image to the local-docker-host machine.

Now whenever you run the maven command:  mvn clean package install  from your project side, you will see that a new Docker image will be built and pushed to the local-docker-host called local/testproject:1.0.0. You can see that by running this command in the local-docker-host machine:  docker images .

You are also able to start a container remotely from your project machine side by running this command:  mvn io.fabric8:docker-maven-plugin:0.30.0:start -P docker . Now you can see your project from the following path:

https://192.168.161.99:8443/TestProject

To stop the started container you can run this command:  mvn io.fabric8:docker-maven-plugin:0.30.0:stop -P docker. 

I hope you find this article helpful.

from DZone Cloud Zone