从Docker中获取Windows可执行二进制文件的最佳实践(Golang)
从Docker中获取Windows可执行二进制文件的最佳实践(Golang) 我正在使用Windows容器运行Docker,需要构建我的镜像,然后获取为我的应用程序编译的Windows可执行文件。以下是我的Dockerfile:
FROM golang:nanoserver
WORKDIR /src
COPY . .
RUN go build -o app
EXPOSE 8080
CMD ["./app"]
这是我正在使用的环境变量:
set GOARCH=amd64
set GOEXE=.exe
set GOOS=windows
我的镜像构建成功,如果Dockerfile中有RUN dir命令,你会看到可执行文件确实存在。
但是,当我尝试像这样从该镜像运行一个容器:docker run -p 8080:8080 webapp,我遇到了这个错误:
docker: Error response from daemon: container 791b7108a0a8dc7ec7b89e619707a6d97858a5483cc2089856076fc2019bf264 encountered an error during hcsshim::System::CreateProcess: failure in a Windows system call: The system cannot find the file specified. (0x2)
[Event Detail: Provider: 00000000-0000-0000-0000-000000000000]
[Event Detail: Provider: 00000000-0000-0000-0000-000000000000]
[Event Detail: onecore\vm\compute\management\orchestration\vmhostedcontainer\processmanagement.cpp(173)\vmcomputeagent.exe!00007FF7E0E69D2B: (caller: 00007FF7E0E1E13A) Exception(2) tid(390) 80070002 The system cannot find the file specified.
CallContext:[\Bridge_ProcessMessage\VmHostedContainer_ExecuteProcess]
Provider: 00000000-0000-0000-0000-000000000000] extra info: {"CommandLine":"./app","User":"ContainerUser","WorkingDirectory":"C:\\src","Environment":{"GOLANG_VERSION":"1.15.6","GOPATH":"C:\\gopath"},"CreateStdInPipe":true,"CreateStdOutPipe":true,"CreateStdErrPipe":true,"ConsoleSize":[0,0]}.
我如何才能成功运行容器,以便可以获取我的二进制文件并使用它们?
更多关于从Docker中获取Windows可执行二进制文件的最佳实践(Golang)的实战教程也可以访问 https://www.itying.com/category-94-b0.html
如果你想在 Docker 中运行你的服务,那么将其编译为 Linux 二进制文件。
目前我确实不太理解你的目标是什么。
更多关于从Docker中获取Windows可执行二进制文件的最佳实践(Golang)的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我移除了Dockerfile中的最后一条命令,基本上使用了docker cp命令将我的二进制文件从容器复制到主机上。
是的,那样可以。我能够复制二进制文件。但是容器的状态是“已退出”,而且即使我使用了 -p 选项,也没有发布任何端口。这会不会以任何方式影响我的二进制文件?
确切地说,我的应用程序只是使用 MongoDB 执行 CRUD 操作,运行二进制文件时,客户端连接没有错误,但尝试 Ping 方法会导致上下文截止时间已过错误。在主机上直接构建我的应用程序时不会出现这个问题。
或者这只是代码本身的问题……
该容器会构建一个应用程序并尝试运行它。由于容器运行的是Linux系统,它无法执行Windows二进制文件。
你可能只想构建镜像,然后使用像 docker cp 这样的工具来提取构建产物。或者,你也可以使用卷(volumes)将产物写入其中,并移除入口点(entrypoint)(或将其更改为其他无操作风格的命令)。
// 代码示例:一个简单的Go程序
func main() {
fmt.Println("hello world")
}
问题在于你的Dockerfile使用了错误的镜像基础。golang:nanoserver 是用于运行Go应用程序的镜像,而不是用于构建Windows可执行文件的最佳选择。以下是修正后的Dockerfile:
# 使用Windows Server Core作为构建环境
FROM mcr.microsoft.com/windows/servercore:ltsc2019 as builder
# 安装Go
RUN powershell -Command \
$ErrorActionPreference = 'Stop'; \
$ProgressPreference = 'SilentlyContinue'; \
Invoke-WebRequest -Uri "https://golang.org/dl/go1.19.windows-amd64.msi" -OutFile go.msi; \
Start-Process msiexec -ArgumentList '/i', 'go.msi', '/quiet', '/norestart' -Wait; \
Remove-Item go.msi
# 设置环境变量
ENV GOPATH=C:\\gopath
ENV PATH="C:\Go\bin;%PATH%"
# 构建应用程序
WORKDIR /src
COPY . .
RUN go build -o app.exe
# 创建最终镜像
FROM mcr.microsoft.com/windows/servercore:ltsc2019
WORKDIR /app
COPY --from=builder /src/app.exe .
EXPOSE 8080
CMD ["app.exe"]
或者,如果你只需要提取二进制文件而不运行容器,可以使用多阶段构建:
# 第一阶段:构建
FROM golang:1.19-windowsservercore-1809 as builder
WORKDIR /src
COPY . .
RUN go build -o app.exe
# 第二阶段:仅用于提取文件
FROM scratch as artifact
COPY --from=builder /src/app.exe /
# 第三阶段:运行
FROM mcr.microsoft.com/windows/servercore:ltsc2019
WORKDIR /app
COPY --from=builder /src/app.exe .
EXPOSE 8080
CMD ["app.exe"]
构建并提取二进制文件:
# 构建镜像
docker build -t myapp .
# 创建容器但不运行
docker create --name extract myapp
# 从容器中复制二进制文件到主机
docker cp extract:/app/app.exe ./app.exe
# 删除临时容器
docker rm extract
如果你只需要构建Windows二进制文件而不需要完整的容器运行时,可以使用交叉编译:
// 在Linux/Mac上构建Windows可执行文件
GOOS=windows GOARCH=amd64 go build -o app.exe main.go
或者在Docker中使用交叉编译:
FROM golang:1.19-alpine as builder
WORKDIR /src
COPY . .
RUN apk add --no-cache gcc musl-dev
RUN GOOS=windows GOARCH=amd64 go build -o app.exe
FROM alpine:latest as artifact
COPY --from=builder /src/app.exe /
错误的具体原因是nanoserver镜像缺少运行Go应用程序所需的依赖。Windows Server Core镜像包含了完整的Windows API支持,更适合运行Go编译的Windows可执行文件。

