0
votes

I have a linux executable. I've built a docker image with centOS 7 which runs ok when executed directly from macOS terminal (macOS Mojave version 10.14.6). The image is built with:

Dockerfile: $ docker build -t my_testi .

FROM scratch
ADD centos-7-x86_64-docker.tar.xz /

LABEL \
    org.label-schema.schema-version="1.0" \
    org.label-schema.name="CentOS Base Image" \
    org.label-schema.vendor="CentOS" \
    org.label-schema.license="GPLv2" \
    org.label-schema.build-date="20200504" \
    org.opencontainers.image.title="CentOS Base Image" \
    org.opencontainers.image.vendor="CentOS" \
    org.opencontainers.image.licenses="GPL-2.0-only" \
    org.opencontainers.image.created="2020-05-04 00:00:00+01:00"

CMD ["/bin/bash"]

ADD executable /bin/
CMD /bin/bash cd /casedir && executable 

I can execute this with command:$ docker run -ti -v /host/casedir/:/casedir my_testi executable /casedir/inputfile.txt. Now, I'm trying to get the docker image to run from a /bin/bash within C++.

Snippet in .cpp:

FILE *pipe;
std::string s="";
pipe = popen("/bin/bash", "w");
fprintf(pipe, "source ~/.bash_profile \n");

    #if defined(__unix__) || defined(__unix) || \
    (defined(__APPLE__) && defined(__MACH__))
                // On MacOX we run with docker
                s += std::string("docker run -ti -v ") +
                     analysispath.parent_path().string() + std::string("/:/casedir my_testi executable /casedir/") +
                inputfiles.back().filename().string(); // docker run -ti -v /host/casedir/:/casedir my_testi executable /casedir/inputfile.txt

    #elif defined(__linux__)
                // On Linux based systems link executable and run
                s += std::string("ln -s ") + std::getenv("EXECUTABLE") + std::string(" executable\n");
                s += std::string("./executable ") +  inputfiles.back().filename().string() + std::string(" > executable_out") + std::string(" \n");

    #endif

fprintf(pipe, "%s", s.c_str());

The problem is that bash in C++ code doesn't run the docker image or perhaps(?) doesn't wait for the command to execute. It jumps straight to next code block. What could be the issue here and how could I get C++ to wait the command is executed?

1
This seems like an incredibly roundabout way to call symlink(2); why not just do that? (Note that if inputfiles comes from somewhere outside your control then it is very easy to use this code to root the entire system, especially in the MacOS case.)David Maze

1 Answers

0
votes

There are two problems which needed addressed. Firstly, the docker command had to be terminated with \n and it had to be run in non-interactive mode i.e. -t instead of -ti. Thus, the command changes to:

s += std::string("docker run -t -v ") +
                     analysispath.parent_path().string() + std::string("/:/casedir my_testi executable /casedir/") +
                inputfiles.back().filename().string() + std::string("\n");