简体   繁体   中英

How to connect to custom network when building image/container in Docker-Java API

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!

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM