You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何将宿主机绝对根目录复制到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

火山引擎 最新活动