Jenkinsfile克隆Git仓库后Dockerfile的COPY指令使用问题咨询
现有写法错误排查
1. Jenkinsfile 冗余问题
你当前的Jenkinsfile中sh 'mkdir repo1'、sh 'cd repo1'都是无效冗余代码:dir('repo1')指令会自动创建不存在的目录,并且自动切换到对应目录执行内部逻辑,不需要手动创建和切换目录。优化后的Clone阶段可简化为:
stage('Clone git') { steps { dir ('repo1') { git ([url : 'https://github.../repo1.git', branch : 'develop', credentialsId : '***']) } dir ('repo2') { git ([url : 'https://github.../repo2.git', branch : 'develop', credentialsId : '***']) } } }
另外Build Docker阶段的sh 'cd ..'需要注意:Jenkins每个sh指令都是独立的shell会话,cd操作不会跨sh生效,你只需要保证docker build命令的执行路径是两个repo所在的父目录即可。
2. Dockerfile 核心错误(含COPY使用不合规问题)
你当前使用了多阶段构建,但逻辑完全不符合预期:
- 多阶段构建中只有最后一个阶段的内容会被保留到最终镜像,前面
node:12.2.0-alpine阶段的COPY结果(也就是存放在/myapp下的两个仓库代码)不会带到后续gradle:6.3-jdk11阶段,第一阶段的操作完全无效 - 第二个阶段的
COPY --chown=gradle:gradle . /repo1只是把构建上下文的所有内容复制到了/repo1,没有单独把repo2的内容提取出来,切换到/repo2时该目录根本不存在,npm install一定会报错 - 把前端ng serve和后端服务放在同一个镜像里不符合容器单进程的最佳实践,若你确实需要这么做,要保证两个服务的运行环境、代码都在同一个最终阶段中。
核心问题解答
核心问题:Dockerfile中仅配置COPY . /myapp是否足够?该指令会将Jenkins构建上下文中所有的repo文件夹都复制到镜像内,还是仅复制镜像相关文件到/myapp,我需要单独复制各个生成的文件夹?
COPY . /目标路径会把**当前docker build指定的构建上下文根目录下的所有内容(包括你克隆的repo1、repo2文件夹,只要没有被.dockerignore规则排除)**全部复制到镜像的目标路径中,所以如果你的构建上下文是两个repo的父目录,这个指令确实可以把两个repo都复制进去。- 你当前的多阶段写法导致第一阶段的COPY结果完全没用,要么放弃多阶段构建,要么需要把前序阶段的内容手动复制到最终阶段。
- 你对repo2的判断错误:多阶段之间的文件系统是完全隔离的,第一阶段复制的repo2不会出现在第二个gradle阶段中,所以必须在需要用到repo2的阶段单独复制,或者把所有操作都放到同一个阶段里。
符合预期的Dockerfile修正示例
如果你确实要把前后端都放在同一个镜像中运行,参考写法如下:
# 选择包含jdk11的基础镜像,后续手动安装前端依赖 FROM gradle:6.3-jdk11 # 安装node、npm和angular-cli(基础镜像默认没有前端运行环境) RUN apt update && apt install -y nodejs npm && npm install -g @angular/cli # 复制构建上下文所有内容(包含repo1、repo2)到镜像内的/myapp COPY . /myapp # 构建后端 WORKDIR /myapp/repo1 RUN gradle build --no-daemon # 构建前端 WORKDIR /myapp/repo2 RUN npm install # 注意:ng serve默认只监听127.0.0.1,外部访问需要加--host 0.0.0.0参数,同时运行两个进程需要自己额外写启动脚本
内容的提问来源于stack exchange,提问作者Darksymphony
相关产品推荐
相关产品推荐

