在Docker中运行Flask和Golang服务器

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

run flask and golang server in docker

问题

我正在尝试在同一个Docker容器中运行一个Go Web服务器和一个Flask服务器。我有一个Dockerfile来构建Flask应用程序。如何更新Dockerfile以构建一个容器来运行Python和Go语言?

项目文件夹

  • pyfolder
    /app.py,
    Dockerfile
  • main.go

main.go

package main

import (
	"fmt"
	"log"
	"net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Println("func called")
}

func main() {
	http.HandleFunc("/", handler)
	log.Fatal(http.ListenAndServe(":8080", nil))
}

app.py

from flask import Flask
import os

app = Flask(__name__)

@app.route("/")
def hello():
    return "Flask inside Docker!!"


if __name__ == "__main__":
    port = int(os.environ.get("PORT", 5000))
    app.run(debug=True,host='0.0.0.0',port=port)

Dockerfile

FROM python:3.6

COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
ENTRYPOINT ["python"]
CMD ["app.py"]

请注意,由于Go和Python是两种不同的语言,它们需要分别构建和运行。你可以使用多阶段构建来实现在同一个Docker容器中运行两者的目的。以下是更新后的Dockerfile:

FROM golang:1.16 AS builder

COPY main.go /go/src/app/
WORKDIR /go/src/app
RUN go build -o main

FROM python:3.6

COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
COPY --from=builder /go/src/app/main /app/main

ENTRYPOINT ["python"]
CMD ["app.py"]

这个更新的Dockerfile使用了多阶段构建。首先,它使用golang:1.16作为构建阶段,将main.go复制到/go/src/app/目录下,并在该目录中构建Go应用程序。然后,它使用python:3.6作为运行阶段,将整个项目文件夹复制到/app目录下,并安装Python依赖。最后,它从构建阶段复制Go应用程序的可执行文件到/app目录下。

这样,你就可以在同一个Docker容器中运行Python和Go应用程序了。

英文:

I am trying to run a go web server and a flask server in the same docker container. I have 1 Docker file to build the flask app. How can I update the Dockerfile to build a container to run both python and golang.

ProjectFolder

  • pyfolder
    /app.py,
    Dockerfile
  • main.go

main.go

package main

import (
	"fmt"
	"log"
	"net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Println("func called")
}

func main() {
	http.HandleFunc("/", handler)
	log.Fatal(http.ListenAndServe(":8080", nil))
}

app.py

from flask import Flask
import os

app = Flask(__name__)

@app.route("/")
def hello():
    return "Flask inside Docker!!"


if __name__ == "__main__":
    port = int(os.environ.get("PORT", 5000))
    app.run(debug=True,host='0.0.0.0',port=port)

Dockerfile

FROM python:3.6

COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
ENTRYPOINT ["python"]
CMD ["app.py"]

答案1

得分: 2

由于您有两个独立的程序,通常您会在两个容器中运行它们,每个容器使用不同的镜像。对于这两种情况,您可以使用各自语言的基本Dockerfile:

# pyfolder/Dockerfile
FROM python:3.6
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt .
COPY . .
EXPOSE 5000
CMD ["./app.py"]
# ./Dockerfile
FROM golang:1.16-alpine AS build
COPY go.mod go.sum .
RUN go mod download
COPY main.go .
RUN go build -o main main.go

FROM alpine
COPY --from=build /go/main /usr/bin/main
EXPOSE 8080
CMD ["main"]

您没有讨论为什么有两个容器或它们如何通信。如果可能的话,您通常希望容器没有任何本地状态,并且仅通过诸如HTTP之类的网络接口进行通信。这意味着您需要一种方法来配置一个服务用于调用另一个服务的网络地址,因为在本地开发环境中运行与在容器中运行时(与部署到云端、在Kubernetes中运行等等)是不同的。环境变量是一种典型的方法;假设Go代码需要调用Python代码:

url := os.Getenv("PYAPP_URL")
if url == "" {
        url = "http://localhost:8080"
}
resp, err := http.Get(url)

一个常见的同时运行多个容器的工具是Docker Compose。它不是唯一的工具,但它是Docker生态系统的标准组成部分,并且比许多其他工具更简单。您可以编写一个描述这两个容器的YAML文件:

version: '3.8'
services:
  pyapp:
    build: ./pyfolder
  server:
    build: . #(包含Go代码和其Dockerfile的目录)
    environment:
      - PYAPP_URL=http://pyapp:5000
    ports:
      - '8080:8080'
    depends_on:
      - pyapp

运行docker-compose up --build将构建这两个镜像并启动这两个容器。

英文:

Since you have two separate programs, you would typically run these in two containers, with two separate images. In both cases you can use a basic Dockerfile for their respective languages:

# pyfolder/Dockerfile
FROM python:3.6
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt .
COPY . .
EXPOSE 5000
CMD ["./app.py"]
# ./Dockerfile
FROM golang:1.16-alpine AS build
COPY go.mod go.sum .
RUN go mod download
COPY main.go .
RUN go build -o main main.go

FROM alpine
COPY --from=build /go/main /usr/bin/main
EXPOSE 8080
CMD ["main"]

You don't discuss at all why you have two containers or how they communicate. You'll frequently want containers to have no local state at all if they can manage it, and communicate only over network interfaces like HTTP. This means you'll need some way to configure the network address one service uses to call another, since it will be different running in a local development environment vs. running in containers (vs. deployed to the cloud, vs. running in Kubernetes, vs....) An environment variable would be a typical approach; say the Go code needs to call the Python code:

url := os.Getenv("PYAPP_URL")
if url == "" {
        url = "http://localhost:8080"
}
resp, err := http.Get(url)

A typical tool to run multiple containers together would be Docker Compose. It's not the only tool, but it's a standard part of the Docker ecosystem and it's simpler than many of the alternatives. You'd write a YAML file describing the two containers:

version: '3.8'
services:
  pyapp:
    build: ./pyfolder
  server:
    build: . # (the directory containing the Go code and its Dockerfile)
    environment:
      - PYAPP_URL=http://pyapp:5000
    ports:
      - '8080:8080'
    depends_on:
      - pyapp

Running docker-compose up --build will build the two images and start the two containers.

答案2

得分: -1

你可以使用Dockerfile中的多阶段构建来完成这个任务。

首先,将Dockerfile移动到与main.go文件相邻的根目录下。

接下来,修改你的Dockerfile如下:

# 获取golang镜像
FROM golang:1.16
WORKDIR .
RUN go build -o app .

# Python部分
FROM python:3.6
WORKDIR /app
# 从第一个阶段复制go二进制文件
COPY --from=0 app ./
# 启动go二进制文件
CMD ["sh", "app"]
# 启动python
RUN pip install -r requirements.txt
ENTRYPOINT ["python"]
CMD ["app.py"]

我认为"The Fool"的建议是正确的,建议将它们分成两个不同的容器。你可以考虑使用docker-compose而不是使用多阶段构建来实现这个目的。

Docker多阶段构建参考文档

英文:

You should be able to accomplish this using a multistage build in your Dockerfile.

First, move the Dockerfile to the root directory next to the main.go.

Next, modify your Dockerfile to

# grab the golang image
FROM golang:1.16
WORKDIR .
RUN go build -o app .

# python portion
FROM python:3.6
WORKDIR /app
# copy the go binary from stage 0
COPY --from=0 app ./
# start the go binary
CMD ["sh", "app"]
# start python
RUN pip install -r requirements.txt
ENTRYPOINT ["python"]
CMD ["app.py"]

I do think The Fool is correct in suggesting to separate these into two different containers. I would look into docker-compose instead of using a multi-stage build for this use.

Docker Multistage Build Reference

huangapple
  • 本文由 发表于 2021年8月9日 00:44:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/68702828.html
匿名

发表评论

匿名网友

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

确定