c++ - 如何使用 Docker 访问输出文件
问题描述
我正在编写一个 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
放置位置是否相同。
解决方案
您需要确保将文件保存到已安装的目录中。现在,看起来您的文件正在作为已安装目录之外的程序的兄弟文件保存。
由于您使用以下方式安装:
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
这将使用您的图像打开一个交互式外壳,然后运行./program some-file.text some-other-file.txt
,然后运行ls
您会看到输出文件result.md
作为program
. 那在您的挂载点之外,这就是为什么您在主机上看不到它的原因。
考虑这个程序。该程序将采用输入文件和输出位置。它将读取 的每一行infile
并将其包装在<p>
. /some
是存储库目录。 /some/res/
是要挂载到的文件夹/repo/res/
。
我通过 为我的程序提供了 2 个参数,这docker run
两个参数都相对于哪个是工作目录。infile
outfile
/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
Dockerfile:
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
测试.cpp:
#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;
}
水库/in.txt:
hello
world
res/out.txt(运行命令后):
<p>hello</p>
<p>world</p>
推荐阅读
- android - Build.VERSION.base_os 在 Android 8 上返回空字符串
- apache-zeppelin - 会适合这种应用吗?
- node.js - 不能在 Node.js 中使用变量名
- javascript - 使用 mongoose update 命令获取受影响的记录
- swift - 如何更改标签的视图
- string - GNAT 18.1 将字符视为字符串
- python - TensorFlow while 循环,其中预测是下一次迭代的输入
- php - 绕过摘要身份验证中间件(zend expressive)?
- google-maps - 找不到符号导入 com.google.android.gms.maps.model.StreetViewSource?
- java - 如何在一个方法中调用 2 个不同的方法