Fixes copyArchiveToContainerCmdImpl fail when hostResource has an emtty dir which gets added as last entry to tar by denlap007 · Pull Request #574 · docker-java/docker-java
This is a simple fix for CopyArchiveToContainerCmdImpl which fails with com.github.dockerjava.api.exception.BadRequestException: Unable to perform tar on host resource /path/to/resource, when the resourceHost is a dir that contains an empty dir which will be added as the last entry to the generated .tar file.
Steps to reproduce
- Create a local dir with the following structure:
|--local_dir
|--a (empty dir)
|--b (dir with file)
|--b.txt (a file)
Name the dirs in the local dir exactly as shown above (preserve names a and b, the file name or content is irrelevant).
- Now we will use the CopyArchiveToContainerCmd with the docker client t o copy the local dir into a container. Run the program:
package fixForCopyArchiveToContainerCmdImpl;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.CreateContainerResponse;
import com.github.dockerjava.core.DockerClientBuilder;
public class Main {
public static void main(String[] args) {
// create docker client
DockerClient docker = DockerClientBuilder.getInstance("unix:///var/run/docker.sock").build();
// create a test container
CreateContainerResponse container = docker.createContainerCmd("progrium/busybox:latest")
.withCmd("/bin/sh", "-c", "while true; do sleep 9999; done")
.exec();
// start the container
docker.startContainerCmd(container.getId()).exec();
// copy data from local dir to container /home path
String localDir = "/home/data";
docker.copyArchiveToContainerCmd(container.getId())
.withHostResource(localDir)
.withRemotePath("/home")
.exec();
}
}
Then, the output will be: com.github.dockerjava.api.exception.BadRequestException: Unable to perform tar on host resource /path/to/resource
In oder to generate the tar file, all files under the local dir must be added to the tarArchiveOutputStream as tarArchiveEntries. The exception happens when the last entry added to the tarArchiveOutputStream is an empty dir.
Notice
In order to view the order with which the files and folders are added to the tarArchiveOutputStream you may add print messages to: com.github.dockerjava.core.util.TarDirWalker class. Specifically, to methods: preVisitDirectory(), visitFile(), e.g.
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
System.out.println("@preVisitDirectory, path: " + dir.toString());
...
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
System.out.println("@visitFile, path: " + file.toString());
...
}
If in any case, the empty folder is not the last entry added to tarArchiveOutputStream the exception won't be reproduced.