docker - 如何在没有 from 标志的情况下编写多阶段 Dockerfile
问题描述
这实际上是我今天提出的这个问题的延续。
--from
我有一个使用标志的多阶段 Dockerfile :
FROM docker.m.our-intra.net/microsoft/dotnet:2.1-sdk
WORKDIR /app
COPY . ./aspnetapp/
WORKDIR /app/aspnetapp
RUN dotnet publish -c Release -o out
FROM docker.m.our-intra.net/microsoft/dotnet:2.1.4-aspnetcore-runtime
WORKDIR /app
COPY --from=docker.m.our-intra.net/microsoft/dotnet:2.1-sdk /app/aspnetapp/MyProject.WebApi/out ./
ENTRYPOINT ["dotnet", "MyProject.WebApi.dll"]
在这个文件的帮助下,我能够成功地在本地构建图像。
但是我不能在我的 Jenkins 管道中使用这个 Dockerfile,因为 Jenkins 服务器引擎低于 17.05 版本并且不会更新(可能稍后但不是现在)。
我是 Docker 和 Jenkins 的新手。如果有人可以帮助我修改 Dockerfile 以便我可以在没有--from
标志的情况下使用它,我将不胜感激。
更新:
楼上说的Dockerfile
不对。Dockerfile
借助我在本地计算机上成功构建映像并成功运行应用程序的工作版本如下:
FROM docker.m.our-intra.net/microsoft/dotnet:2.1-sdk AS build
WORKDIR /app
COPY . ./aspnetapp/
WORKDIR /app/aspnetapp
RUN dotnet publish -c Release -o out
FROM docker.m.our-intra.net/microsoft/dotnet:2.1.4-aspnetcore-runtime AS runtime
WORKDIR /app
COPY --from=build /app/aspnetapp/MyProject.WebApi/out ./
ENTRYPOINT ["dotnet", "MyProject.WebApi.dll"]
更新 2:
我正在尝试遵循 Carlos 的建议,现在我有两个 docker 文件。
这是我的Docker-build
:
FROM docker.m.our-intra.net/microsoft/dotnet:2.1-sdk
WORKDIR /app
COPY . ./aspnetapp/
WORKDIR /app/aspnetapp
RUN dotnet publish -c Release -o out
这是我的Dockerfile
:
FROM docker.m.our-intra.net/microsoft/dotnet:2.1.4-aspnetcore-runtime
COPY . .
ENTRYPOINT ["dotnet", "MyProject.WebApi.dll"]
这是我的Jenkinsfile
:
def docker_repository_url = 'docker.m.our-intra.net'
def artifact_group = 'some-artifact-group'
def artifact_name = 'my-service-api'
pipeline {
agent {
label 'build'
}
stages {
stage('Checkout') {
steps {
script {
echo 'Checkout...'
checkout scm
echo 'Checkout Completed'
}
}
}
stage('Build') {
steps {
script {
echo 'Build...'
sh 'docker version'
sh 'docker build -t fact:v${BUILD_NUMBER} -f Dockerfile-build .'
echo 'Build Completed'
}
}
}
stage('Extract artifact') {
steps {
script {
echo 'Extract...'
sh 'docker create --name build-stage-container fact:v${BUILD_NUMBER}'
sh 'docker cp build-stage-container:/app/aspnetapp/MyProject.WebApi/out .'
sh 'docker rm -f build-stage-container'
echo 'Extract Completed'
}
}
}
stage('Copy compiled artifact') {
steps {
script {
echo 'Copy artifact...'
sh "docker build -t ${docker_repository_url}/${artifact_group}/${artifact_name}:v${BUILD_NUMBER} -f Dockerfile ."
echo 'Copy artifact Completed'
}
}
}
stage('Push image') {
steps {
script {
withCredentials([[
$class: 'UsernamePasswordMultiBinding',
credentialsId: 'jenkins',
usernameVariable: 'USERNAME',
passwordVariable: 'PASSWORD'
]]) {
def username = env.USERNAME
def password = env.PASSWORD
echo 'Login...'
sh "docker login ${docker_repository_url} -u ${username} -p ${password}"
echo 'Login Successful'
echo 'Push image...'
sh "docker push ${docker_repository_url}/${artifact_group}/${artifact_name}:v${BUILD_NUMBER}"
echo 'Push image Completed'
}
}
}
}
}
}
所有步骤都成功了,但是当我尝试在本地运行图像(从 Maven 中提取它之后)或在 OpehShift 集群上运行它时失败并说:
您的意思是运行 dotnet SDK 命令吗?请从以下位置安装 dotnet SDK:http: //go.microsoft.com/fwlink/ ?LinkID=798306&clcid=0x409
我究竟做错了什么?
解决方案
TL;DR:您需要自己复制底层功能,在 Docker 之外
首先,您使用的--from
选项错误。要从之前的构建阶段复制,您必须引用其索引或名称,例如:
FROM docker.m.our-intra.net/microsoft/dotnet:2.1-sdk
...
FROM docker.m.our-intra.net/microsoft/dotnet:2.1.4-aspnetcore-runtime
COPY --from=0 /app/aspnetapp/MyProject.WebApi/out ./
或者
FROM docker.m.our-intra.net/microsoft/dotnet:2.1-sdk AS build-stage
...
FROM docker.m.our-intra.net/microsoft/dotnet:2.1.4-aspnetcore-runtime
COPY --from=build-stage /app/aspnetapp/MyProject.WebApi/out ./
使用您当前的 Dockerfile,它会尝试从上游 docker 映像复制文件,而不是从之前的构建阶段。
其次,您不能使用 17.05 之前的版本进行多阶段 Docker 构建。您需要在 Docker 之外自己复制底层功能。
为此,您可以使用一个 Dockerfile 来构建您的工件并基于该映像运行一个一次性容器,从中提取工件。你不需要运行容器,你可以简单地创建它docker create
(这将创建可写容器层):
docker create --name build-stage-container build-stage-image
docker cp build-stage-container:/app/aspnetapp/MyProject.WebApi/out .
然后,您可以使用第二个 Dockerfile 来构建镜像,复制从前一阶段提取的工件,并使用COPY
构建上下文中的简单内容。
推荐阅读
- python-3.x - WebDriverException:消息:“chromedriver”可执行文件需要在 PATH 中使用 Google Colaboratory 上的 python 语言
- mysql - 合并mysql查询
- c++ - 如何强制用户将函数参数输入为 Unicode 字符串?
- python - 在 Python 中读取文本
- angular - 在同一字段内选择和输入角度材料
- python - 当我在 Lasso Regression 中拆分训练集和测试集时,R^2 为负数
- laravel - 如何使用 Laravel Livewire 和 Spatie 媒体库上传图片?
- sql - 基于主工作表中的列在excel中创建多个工作表
- android - 使用 FileProvider 从图库中打开图像
- python - CSP:为什么“none”和“unsafe-inline”被解释为主机名?