无法通过Docker-Compose运行Go可执行文件。

huangapple go评论51阅读模式
英文:

Can't get docker to run Go executable using Docker-Compose

问题

我正在使用Go创建一个简单的Rest API,并希望使用Docker进行容器化以进行部署。我的Dockerfile如下:

FROM golang:1.19

# 要暴露的端口
ENV PORT=8080

WORKDIR /go/src/app

# 安装libvips
RUN apt-get update && apt-get install -y libvips-dev

# 复制go.mod和go.sum
COPY go.mod go.sum ./

# 安装Go依赖项
RUN go mod download

# 为libvips设置PKG_CONFIG_PATH
ENV PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig
RUN pkg-config --libs vips

# 复制源代码
COPY . .

# 取消注释以构建应用程序
# 构建应用程序
RUN go build -o main .

# 暴露端口
EXPOSE 8080

# 运行应用程序
CMD ["./main"]

而我的docker-compose文件如下:

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: backend
    command: ./main
    ports:
      - "3000:8080"
    volumes:
      - .:/go/src/app

我对Docker和容器化还不太熟悉,但我认为这应该在设置方面是有效的(注意:之前已经有几次成功,但最近因某种原因停止工作)。我遇到以下错误:Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "./main": stat ./main: no such file or directory: unknown

这个错误让我认为我的可执行文件没有在工作目录中构建,但我不确定它在哪里构建,因为我已经使用相对路径设置了构建命令。对于可能导致这个问题的原因有什么想法吗?

英文:

I'm making a simple Rest API using Go and I want to containerize it using docker for deployment. My Dockerfile looks like this

FROM golang:1.19

# Port to expose
ENV PORT=8080

WORKDIR /go/src/app

# Install libvips
RUN apt-get update && apt-get install -y libvips-dev

# Copy go.mod and go.sum
COPY go.mod go.sum ./

# Install go dependencies
RUN go mod download

# Set PKG_CONFIG_PATH for libvips
ENV PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig
RUN pkg-config --libs vips

# Copy the source code
COPY . .

# Uncomment to build the app 
# Build the app 
RUN go build -o main .

# Expose the port
EXPOSE 8080

# Run the app
CMD ["./main"]

and my docker-compose file looks like this:

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: backend
    command: ./main
    ports:
      - "3000:8080"
    volumes:
      - .:/go/src/app

I'm new to docker and containerization, but I think this should work in terms of setup (Note: It has worked a few times before, but recently stopped working for some reason). I get the following error: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "./main": stat ./main: no such file or directory: unknown.

This error leads me to believe that my exe is not being built in the working directory, but I am unsure where it gets built since I've set the build command using relative paths. Any idea on what could be causing this issue?

答案1

得分: 1

不应该在 docker-compose 文件中包括 volumes 映射(.:/go/src/app)。

这样做会覆盖容器中的文件夹,用主机的文件夹替换它。

两者之间的一个关键区别是容器的文件夹包括 go build 的输出。你正在构建二进制文件(/go/src/app/main),然后用 volumes 映射覆盖整个文件夹。

注意 最好的做法是使用 ENTRYPOINT 而不是 CMD 来运行二进制文件,即 ENTRYPOINT ["./main"]CMD 的值会在运行容器时被任何提供的参数覆盖,而 ENTRYPOINT 只能通过显式设置 --entrypoint 标志来覆盖。按照惯例,使用 ENTRYPOINT 来定义容器始终要调用的二进制文件(以及任何标志),并使用 CMD 用于可以被覆盖的可选标志。

英文:

You shouldn't include the volumes mapping (.:/go/src/app) in the docker-compose file.

When you do this, you're overwriting the container's folder with your host's folder.

A key difference between the two is that the container's folder includes the output from go build. You're building the binary (/go/src/app/main) and then overwriting the entire folder with the volumes mapping.

> NOTE It's better practice to use ENTRYPOINT rather than CMD to run the binary, i.e. ENTRYPOINT ["./main"]. The value(s) of CMD are overwritten by any parameters provided when the container is run whereas ENTRYPOINT may only be overwritten by explicitly setting the --entrypoint flag. Conventionally, use ENTRYPOINT to define the binary (and any flags) that must always be invoked by the container and use CMD for optional flags that may be overwritten.

答案2

得分: 0

这是一个稍微偏离主题的建议,但在使用libvips时,请使用--no-install-recommends选项。Debian软件包在libvips-dev的建议列表中包括libvips-tools,而libvips-tools又会引入libvips的GUI和大部分X11。

您可以通过以下方式看到这种差异:

$ docker run -it --rm golang:1.19
root@c54a0cab0cb0:/go# 
root@c54a0cab0cb0:/go# 
root@c54a0cab0cb0:/go# apt update
...
root@c54a0cab0cb0:/go# apt install libvips-dev
...
需要下载 189 MB 的存档。
此操作完成后,将使用额外 740 MB 的磁盘空间。
您要继续吗?[Y/n] ^C
...

因此,常规安装需要740MB的空间。但是:

root@c54a0cab0cb0:/go# apt install libvips-dev --no-install-recommends
需要下载 92.2 MB 的存档。
此操作完成后,将使用额外 374 MB 的磁盘空间。
您要继续吗?[Y/n] ^C

大约一半的大小。

英文:

This is a slight tangent, but use --no-install-recommends with libvips. The Debian package includes libvips-tools in the recommends list for libvips-dev, and that in turn will pull in the libvips GUI and most of X11.

You can see the difference it makes like this:

$ docker run -it --rm golang:1.19
root@c54a0cab0cb0:/go# 
root@c54a0cab0cb0:/go# 
root@c54a0cab0cb0:/go# apt update
...
root@c54a0cab0cb0:/go# apt install libvips-dev
...
Need to get 189 MB of archives.
After this operation, 740 MB of additional disk space will be used.
Do you want to continue? [Y/n] ^C
...

So a reular install is 740mb of space. But:

root@c54a0cab0cb0:/go# apt install libvips-dev --no-install-recommends
Need to get 92.2 MB of archives.
After this operation, 374 MB of additional disk space will be used.
Do you want to continue? [Y/n] ^C

About half the size.

答案3

得分: 0

当您运行容器时,CMD 的值将被提供的任何参数覆盖。最好使用 ENTRYPOINT 来运行二进制文件,即 ENTRYPOINT ["./main"]。

英文:

When you run the container, the value of CMD will be overwritten by any parameters provided. It is better to use ENTRYPOINT instead of CMD to run binary files, that is ENTRYPOINT ["./main"].

huangapple
  • 本文由 发表于 2023年2月16日 11:40:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/75467627.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定