如何将宿主机绝对根目录复制到Docker镜像?解决COPY命令报错
解决Dockerfile复制宿主机绝对目录的问题
嘿,这个问题我之前也碰到过!本质是Docker构建上下文的限制在搞鬼——Docker构建镜像时,只能访问构建上下文目录(以及它的子目录)里的文件,没法直接读取宿主机任意绝对路径下的内容,这就是你看到那个no such file or directory错误的原因。下面给你几个实用的解决办法:
方法1:调整构建上下文范围(不推荐大上下文)
Docker的COPY指令是从构建上下文里取文件的,如果你非要直接用宿主机的/data/resources/config,可以把构建上下文设为根目录,但要注意这样会把整个根目录的内容都传给Docker daemon,构建速度极慢还可能有安全风险:
# 把根目录作为构建上下文 docker build -t your-service-image /
然后修改Dockerfile里的COPY路径(去掉开头的/):
FROM java:latest WORKDIR /tmp MAINTAINER Service COPY target/Service-1.3.jar . RUN mkdir -p /data/resources # 因为上下文是根目录,所以直接写相对路径 COPY data/resources/config /data/resources
方法2:复制目标目录到构建上下文(简单稳妥)
更推荐的方式是先把需要的目录复制到你的Dockerfile所在的项目目录(也就是默认的构建上下文):
# 假设你的Dockerfile在/home/your-service-project下 cp -r /data/resources/config /home/your-service-project/
然后修改Dockerfile里的COPY指令:
FROM java:latest WORKDIR /tmp MAINTAINER Service COPY target/Service-1.3.jar . RUN mkdir -p /data/resources # 现在config在构建上下文里,直接复制 COPY config /data/resources
最后在项目目录下正常执行构建:
docker build -t your-service-image .
方法3:用BuildKit临时挂载宿主机目录(灵活高效)
如果你的Docker版本是18.09及以上(支持BuildKit),可以用构建时挂载的方式,不用提前复制文件。先修改Dockerfile(注意开头要指定Dockerfile语法版本):
# syntax=docker/dockerfile:1.4 FROM java:latest WORKDIR /tmp MAINTAINER Service COPY target/Service-1.3.jar . RUN mkdir -p /data/resources # 临时挂载宿主机的/config目录到构建容器的/tmp/config,然后复制 RUN --mount=type=bind,source=/data/resources/config,target=/tmp/config \ cp -r /tmp/config /data/resources
然后开启BuildKit执行构建:
# 临时开启BuildKit(如果没默认开启) DOCKER_BUILDKIT=1 docker build -t your-service-image .
方法4:运行容器时挂载卷(适合动态配置)
如果这个config目录不需要打包进镜像,而是希望容器运行时直接读取宿主机的最新配置,那完全不用在Dockerfile里COPY,运行容器时用-v参数挂载即可:
docker run -d -v /data/resources/config:/data/resources/config your-service-image
这种方式适合配置文件经常变动的场景,不用每次改配置都重新构建镜像。
内容的提问来源于stack exchange,提问作者Abdullah G




