我正在尝试在docker中安装HTTPD,我写了一个像这样的dockerfile:
FROM centos
VOLUME /var/log/httpd
VOLUME /etc/httpd
VOLUME /var/www/html
# Update Yum Repostory
RUN yum clean all && \
yum makecache fast && \
yum -y update && \
yum -y install httpd
RUN yum clean all
EXPOSE 80
CMD /usr/sbin/httpd -D BACKGROUND && tail -f /var/log/httpd/access_log
如果我在没有主机卷的情况下运行图像,它会起作用,但如果我使用参数:
则会失败--volume /data/httpd/var/www/html:/var/www/html --volume /data/httpd/var/log:/var/log --volume /data/httpd/etc:/etc/httpd
错误信息是:
httpd: Could not open configuration file /etc/httpd/conf/httpd.conf: No such file or directory
我检查了空的挂载点:
# ll /data/httpd/etc/
total 0
但是如果我没有默认使用“音量”停靠者复制文件到临时文件夹:
# ll /var/lib/docker/volumes/04f083887e503c6138a65b300a1b40602d227bb2bbb58c69b700f6ac753d1c34/_data
total 4
drwxr-xr-x. 2 root root 35 Nov 3 03:16 conf
drwxr-xr-x. 2 root root 78 Nov 3 03:16 conf.d
drwxr-xr-x. 2 root root 4096 Nov 3 03:16 conf.modules.d
lrwxrwxrwx. 1 root root 19 Nov 3 03:16 logs -> ../../var/log/httpd
lrwxrwxrwx. 1 root root 29 Nov 3 03:16 modules -> ../../usr/lib64/httpd/modules
lrwxrwxrwx. 1 root root 10 Nov 3 03:16 run -> /run/httpd
所以我很困惑,为什么码头工人拒绝将它们复制到指定位置?以及如何解决这个问题?
答案 0 :(得分:2)
这确实是一种记录在案的行为:
创建容器时初始化卷。如果容器的 基本映像包含指定安装点的数据,即现有数据 在卷初始化时将其复制到新卷中。 (注意这个 安装主机目录时不适用。)
即。当您挂载 / etc / httpd 卷 - volume / data / httpd / etc:/ etc / httpd 时,不会复制任何数据。
您还可以看到https://github.com/docker/docker/pull/9092更详细地讨论它为什么会这样运作(如果您感兴趣的话)。
通常的解决方法是将初始数据复制到ENTRYPOINT或CMD脚本中的卷文件夹(来自容器内), 万一它是空的。
请注意,您的初始数据集必须保留在卷文件夹之外(例如,作为/ opt中的.tar文件),以使其正常工作,因为卷文件夹将被安装在其上的主机文件夹遮蔽。
下面给出了一个示例Dockerfile和Script,它演示了行为:
示例Dockerfile
FROM debian:stable
RUN mkdir -p /opt/test/; touch /opt/test/initial-data-file
VOLUME /opt/test
示例脚本(尝试各种卷映射)
#Build image
>docker build -t volumetest .
Sending build context to Docker daemon 2.56 kB
Step 0 : FROM debian:stable
---> f7504c16316c
Step 1 : RUN mkdir -p /opt/test/; touch /opt/test/initial-data-file
---> Using cache
---> 1ea0475e1a18
Step 2 : VOLUME /opt/test
---> Using cache
---> d8d32d849b82
Successfully built d8d32d849b82
#Implicit Volume mapping (as defined in Dockerfile)
>docker run --rm=true volumetest ls -l /opt/test
total 0
-rw-r--r-- 1 root root 0 Nov 4 18:26 initial-data-file
#Explicit Volume mapping
> docker run --rm=true --volume /opt/test volumetest ls -l /opt/test/
total 0
-rw-r--r-- 1 root root 0 Nov 4 18:26 initial-data-file
#Explicitly Mounted Volume
>mkdir test
>docker run --rm=true --volume "$(pwd)/test/:/opt/test" volumetest ls -l /opt/test
total 0
这是一个简单的入口点脚本,说明了可能的解决方法:
#!/bin/bash
VOLUME=/opt/test
DATA=/opt/data-volume.tar.gz
if [[ -n $(find "$VOLUME" -maxdepth 0 -empty) ]]
then
echo Preseeding VOLUME $VOLUME with data from $DATA...
tar -C "$VOLUME" -xvf "$DATA"
fi
"$@"
将以下内容添加到Dockerfile
COPY data-volume.tar.gz entrypoint /opt/
ENTRYPOINT ["/opt/entrypoint"]
首先运行:
>docker run --rm=true --volume "$(pwd)/test/:/opt/test" volumetest ls -l /opt/test
Preseeding VOLUME /opt/test with data from /opt/data-volume.tar.gz...
preseeded-data
total 0
-rw-r--r-- 1 1001 users 0 Nov 4 18:43 preseeded-data
后续运行:
>docker run --rm=true --volume "$(pwd)/test/:/opt/test" volumetest ls -l /opt/test
ls -l /opt/test
total 0
-rw-r--r-- 1 1001 users 0 Nov 4 18:43 preseeded-data
请注意,卷文件夹仅将填充数据, 如果它之前完全是空的。