我正在编写C ++程序,并希望在其上使用Docker。 Dockerfile
如下所示:
FROM gcc:7.2.0
ENV MYP /repo
WORKDIR ${MYP}
COPY . ${MYP}
RUN /bin/sh -c 'make'
ENTRYPOINT ["./program"]
CMD ["file1", "file2"]
此程序需要两个输入文件( file1 和 file2 ),并按如下方式构建和执行:
docker build -t image .
docker run -v /home/user/tmp/:/repo/dir image dir/file1 dir/file2
这些输入文件位于/home/user/tmp/
的主机中。在原始存储库(repo/
)中,可执行文件位于其根目录中,生成的输出文件保存在同一文件夹中(即,它们看起来像repo/program
并且repo/results.md
)。
当我运行上面的docker run
命令时,我可以从标准输出中看到可执行文件正确读取输入文件并生成预期结果。但是,我希望写入的输出文件(由带有std::ofstream
的程序生成)也保存在已安装的目录/home/user/tmp/
中,但不是。
如何访问此文件?有没有一种直接的方法来使用docker音量机制来获取它?
Docker版本为18.04.0-ce,构建3d479c0af6。
修改
有关程序如何保存输出文件result.md
的相关代码如下:
std::string filename ("result.md"); // in the actual code this name is not hard-coded and depends on intput, but it will not include / chars
std::ofstream output_file;
output_file.open(filename.data(), std::ios::out);
output_file << some_data << etc << std::endl;
...
output_file.close();
在实践中,程序以program file1 file2
运行,输出将保存在工作目录中,无论是否与program
放置相同。
答案 0 :(得分:2)
您需要确保将文件保存到已安装的目录中。现在,看起来你的文件被保存为你的程序的兄弟,它正好在安装目录之外。
因为你搭载:
docker run -v /home/user/tmp/:/repo/dir image dir/file1 dir/file2
/repo/dir
是您将看到更改的唯一文件夹。但是如果要将文件保存到/repo
,它们将保存在那里,但在运行后在主机系统上看不到。
考虑如何打开输出文件:
std::string filename ("result.md"); // in the actual code this name is not hard-coded and depends on intput, but it will not include / chars
std::ofstream output_file;
output_file.open(filename.data(), std::ios::out);
output_file << some_data << etc << std::endl;
...
output_file.close();
由于您将输出文件设置为"result.md"
且没有路径,因此它将作为程序的兄弟打开。
如果你要跑
docker run -it --rm --entrypoint=/bin/bash image
将使用您的图片打开交互式shell,然后运行./program some-file.text some-other-file.txt
,然后运行ls
您会看到输出文件result.md
作为program
的兄弟。这是在你的挂载点之外,这就是你在主机上没有看到它的原因。
考虑一下这个程序。该程序将采用输入文件和输出位置。它将在infile
的每一行中读取并将其包装在<p>
中。 /some
是存储库目录。 /some/res/
是将挂载到/repo/res/
的文件夹。
我通过docker run
,infile
和outfile
为我的程序提供了2个参数,这两个参数都与作为工作目录的/repo
相关。
我的程序然后保存到挂载点(outfile
)内的/repo/res/
位置。完成docker run
后,会填充/some/res/out.txt
。
.
├── Dockerfile
├── README.md
├── makefile
├── res
│ └── in.txt
└── test.cpp
docker build -t image .
docker run --rm -v ~/Desktop/some/res/:/repo/res/ image ./res/in.txt ./res/out.txt
FROM gcc:7.2.0
ENV MYP /repo
WORKDIR ${MYP}
COPY . ${MYP}
RUN /bin/sh -c 'make'
ENTRYPOINT ["./test"]
CMD ["file1", "file2"]
test: test.cpp
g++ -o test test.cpp
.PHONY: clean
clean:
rm -f test
#include <fstream>
#include <iostream>
#include <string>
int main(int argc, char **argv) {
if (argc < 3) {
std::cout << "Usage: test [infile] [outfile]" << std::endl;
return 1;
}
std::cout << "All args" << std::endl;
for (int i = 0; i < argc; i++) {
std::cout << argv[i] << std::endl;
}
std::string line;
std::ifstream infile(argv[1]);
std::ofstream outfile(argv[2]);
if (!(infile.is_open() && outfile.is_open())) {
std::cerr << "Unable to open files" << std::endl;
return 1;
}
while (getline(infile, line)) {
outfile << "<p>" << line << "</p>" << std::endl;
}
outfile.close();
return 0;
}
hello
world
<p>hello</p>
<p>world</p>
答案 1 :(得分:0)
我想发布我现在正在使用的Dockerfile
,希望它对某些人有用。不需要为输出文件指定名称或路径。输出文件总是写在$PWD
中。
FROM alpine:3.4
LABEL version="1.0"
LABEL description="some nice description"
LABEL maintainer="user@home.com"
RUN apk update && apk add \
gcc \
g++ \
make \
git \
&& git clone https://gitlab.com/myuser/myrepo.git \
&& cd myrepo \
&& make \
&& cp program /bin \
&& rm -r /myrepo \
&& apk del g++ make git
WORKDIR /tmp
ENTRYPOINT ["program"]
我只需要运行:
docker run --rm -v $PWD:/tmp image file1 file2
内部在映像中,工作目录为tmp
,并且无法更改,这是传递给卷-v
选项的目录。运行映像后,所有输出文件将保存在主机的相应工作目录中。