- 背景故事
- dockerfile volume局限
- 另辟蹊径解决方法
背景故事
在gitlab-ci中使用acme.sh生成证书的时候,遇上了一些和挂载有关的问题。
acme.sh这个开源软件的stateless模式会根据本机的一份配置文件生成一份密文,让服务器特殊接口返回这份密文用以验证域名的所有权,之后会生成一张https证书以供这个域名使用。同时,如果在另外一台机器上的话,就会生成另外一份密文。所以,要让接口通用的话,最好是让所有机器上使用的密文保持统一。
ACCOUNT_THUMBPRINT便是acme.sh需要服务器返回的密文
在acme.sh的官方镜像中,这份密文会生成在/acme.sh目录下。
dockerfile volume局限
所以一开始在我看来如果想让所有机器的密文都保持一致的话,最好的方法就是直接commit这个容器,让它成为一个新的镜像。自然会把/acme.sh目录下的所有文件自动保存下来。但其实并不是,当你使用新镜像的话,这个/acme.sh的目录下除了account.conf别无他物,自然不会为你保留密文。
在这样的情况下,我考虑了两种情况,一种是Docker镜像本身的问题,另一种是acme.sh自己删除了。
经过排查和看源码,其实从文章名字就可以看出其实是dockerfile中volume的问题,看一下acme.sh的dockerfile
可以看到他将/acme.sh设置为了挂载目录。
需要注意的是,大部分情况下,如果你将一个目录设置为了挂载目录,你将无法再修改这个镜像中这个目录下的文件。 所以,你需要知道你所使用的源镜像的Dockerfile是否使用了volume。但如果你在这条命令之前的修改依然是有效的。
FROM neilpang/acme.sh
RUN touch /acme.sh yr12dong.txt
RUN ls /acme.sh
看一下这份Dockerfile,他的/acme.sh 下就不会出现yr12dong.txt这份文件
可以看到上图中,运行RUN ls acme.sh的命令后,没有出现yr12dong.txt
另辟蹊径解决方法
那如何解决这个问题?你无法修改你引用的Docker 源镜像,就像你无法改变你接手🐘山的代码一样。但是还好,你可以使用COPY 或者 ADD命令,来解决这个问题。
FROM neilpang/acme.sh
RUN touch /acme.sh yr12dong.txt
RUN ls /acme.sh
COPY README.md /acme.sh
RUN ls /acme.sh
在刚刚的dockerfile后面,加入COPY命令,情况大有改观。
可以看到在VOLUME(源镜像中)之后使用COPY命令,你就突破了无法修改挂载目录下文件的现实了。
希望大家如果遇到使用commit镜像之后,却发现自己没有得到预想中的结果时,能在看完这篇文档之后,马上知道是Dockerfile volume挂载的局限性。