3

I am using the Docker-Java API found here https://github.com/docker-java/docker-java.

I have a dockerfile that I have to build 3 containers for. I am trying to automate the process of building 3 images and the commands to go with them when running the shell inside. The 3 containers must be in the same local network in order for them to communicate. I am able to do this manually just fine...

So first, using the docker-java API, I am building a custom network using the following function:

private void createNetwork() {
    CreateNetworkResponse networkResponse = dockerClient.createNetworkCmd()
        .withName("ETH")
        .withDriver("bridge")
        .withAttachable(true)
        .exec();
    System.out.printf("Network %s created...\n", networkResponse.getId());
}

This works great, and if I run docker network ls, I can see the ETH network listed.

The next step is building the image. I am running the following function:

public String buildImage(String tag) {
    String imageID = dockerClient.buildImageCmd()
        .withDockerfile(new File("/Dockerfile"))
        .withPull(true)
        .withNoCache(false)
        .withTags(new HashSet<>(Collections.singletonList(tag)))
        .withNetworkMode("ETH")
        .exec(new BuildImageResultCallback())
        .awaitImageId();
    System.out.println("Built image: " + imageID);
    return imageID;
}

So the image builds fine and I can see the image when I run the docker images command in terminal. I do expect that the image to be connected to the ETH network, but I do not see that.

I thought that maybe I have to connect to the network when creating the container instead then, so I pass the same commands I would if I were to manually do this when building the container through the following function:

private String createContainer(String name, String imageID, int port) {
        CreateContainerResponse container = dockerClient
                .createContainerCmd(name)
                .withImage(imageID)
                .withCmd("docker", "run", "--rm", "-i", "-p", port + ":" + port, "--net=ETH", name)
                .withExposedPorts(new ExposedPort(port))
                .exec();
        dockerClient.startContainerCmd(container.getId()).exec();
        return container.getId();
}

Unfortunately, when passing in the arguments like this, the built container does not show up in the ETH network when running the command docker network inspect ETH.

I'm not sure what I am doing wrong. If I build the image using the API, and then run the following command manually, docker run --rm -it -p 8545:8545 --net=ETH miner_one everything works fine. Any help would be greatly appreciated. Thank you!

  • Images aren't connected to networks. (What's the IP address of a jar file?) You almost certainly need to include it in your call to create the container; you would not specify `docker run` options there (or a `docker run` command even) but instead specify the same options using the Docker API. – David Maze Nov 25 '19 at 16:53
  • Ahh @DavidMaze thank you. That's helpful. In that case, I need to be attaching to the ETH network in the createContainer function by specifying the ETH network there.. but I don't see any method call to set the network when calling ```.createContainer()```. – Sameet Ahmed Nov 25 '19 at 17:00

1 Answers1

2

The docker-java client supports a subset of the Docker Remote API. To connect to a network when you create the container set the NetworkMode field (see HostConfig -> NetworkMode in Container Create section)

Network mode to use for this container. Supported standard values are: bridge, host, none, and container:. Any other value is taken as a custom network's name to which this container should connect to.

Therefore, in order for the container to connect to the custom network set the value of the network mode to ETH.

In Java, for older versions of the Docker-Java client, use the withNetworkMode() method:

CreateContainerResponse container = dockerClient
                .createContainerCmd(name)
                .withImage(imageID)
                .withNetworkMode("ETH")
                ...

In the latest version, the methods in CreateContainerCmd used to set the fields in HostConfig are deprecated. Use withHostConfig() instead:

 CreateContainerResponse container = dockerClient.createContainerCmd(name)
     .withImage(imageID)
     .withHostConfig(HostConfig.newHostConfig().withNetworkMode("ETH"))
     ...

Here is a basic example:

List<Network> networks = dockerClient.listNetworksCmd().withNameFilter("ETH").exec();
    if (networks.isEmpty()) {
      CreateNetworkResponse networkResponse = dockerClient
          .createNetworkCmd()
          .withName("ETH")
          .withAttachable(true)
          .withDriver("bridge").exec();
      System.out.printf("Network %s created...\n", networkResponse.getId());
    }

    CreateContainerResponse container = dockerClient
        .createContainerCmd("ubuntu")
        .withName("my-ubuntu")
        .withCmd("sleep", "10")
        .withHostConfig(HostConfig
            .newHostConfig()
            .withNetworkMode("ETH")
            .withAutoRemove(true))
        .exec();

    String containerId = container.getId();
    dockerClient.startContainerCmd(containerId).exec();

    Network ethNetwork = dockerClient.inspectNetworkCmd()
        .withNetworkId("ETH")
        .exec();

    Set<String> containerIds = ethNetwork.getContainers().keySet();
    if(containerIds.contains(containerId)) {
      System.out.printf("Container with id:%s is connected to network %s%n", containerId, ethNetwork.getName());
    } 

It creates a network named ETH and a container my-ubuntu from an ubuntu image. The container is connected to the ETH network.

Hope this helps.

b0gusb
  • 4,283
  • 2
  • 14
  • 33
  • I tried adding the code ``` .withHostConfig(HostConfig.newHostConfig().withNetworkMode("ETH"))```, but I still don't see the container when running ```docker network inspect ETH```. – Sameet Ahmed Nov 26 '19 at 16:17
  • @SameetAhmed Is the container running when you inspect the `ETH` network? When the container exits it is removed from the containers list in the network. I have updated my answer adding a working example. – b0gusb Nov 27 '19 at 08:42