英文:
how to make container for multiple servers in one code base to deploy golang app with docker?
问题
我有一个包含多个服务器的代码库,结构如下:
// Golang Apps
- account = 端口 4001
- event = 端口 4002
- place = 端口 4003
// Node.js
- gateway = 端口 4000
我通常在本地使用以下脚本运行:
// script.sh
#!/bin/bash
EnvAPP="${ENV_APP:-dev}"
function cleanup {
kill "$ACCOUNTS_PID"
kill "$EVENTS_PID"
kill "$PLACES_PID"
}
trap cleanup EXIT
go build -tags $EnvAPP -o ./tmp/srv-accounts ./cmd/server/accounts
go build -tags $EnvAPP -o ./tmp/srv-events ./cmd/server/events
go build -tags $EnvAPP -o ./tmp/srv-places ./cmd/server/places
./tmp/srv-accounts &
ACCOUNTS_PID=$!
./tmp/srv-events &
EVENTS_PID=$!
./tmp/srv-places &
PLACES_PID=$!
sleep 1
node ./cmd/gateway/index.js
在生产环境中,我是否可以为这种情况创建一个Dockerfile?我是否应该在Dockerfile中运行script.sh?关于Dockerfile中应该使用的镜像,我没有头绪,因为代码库中有多个服务器运行,并且服务器的端口也是一个问题。
也许你们中的某个人曾经遇到过这种情况?了解如何解决这个问题将会很棒。
对于这个问题,我正在使用 GraphQL Federation(Go),所以我有多个服务和一个网关(Node.js)。
我想要将其部署到生产环境中。
英文:
I have a repo that has multiple servers gonna running. the structure like this
// Golang Apps
- account = port 4001
- event = port 4002
- place = port 4003
// Node js
- gateway = port 4000
I usually run in local using script like this
// script.sh here:
#!/bin/bash
EnvAPP="${ENV_APP:-dev}"
function cleanup {
kill "$ACCOUNTS_PID"
kill "$EVENTS_PID"
kill "$PLACES_PID"
}
trap cleanup EXIT
go build -tags $EnvAPP -o ./tmp/srv-accounts ./cmd/server/accounts
go build -tags $EnvAPP -o ./tmp/srv-events ./cmd/server/events
go build -tags $EnvAPP -o ./tmp/srv-places ./cmd/server/places
./tmp/srv-accounts &
ACCOUNTS_PID=$!
./tmp/srv-events &
EVENTS_PID=$!
./tmp/srv-places &
PLACES_PID=$!
sleep 1
node ./cmd/gateway/index.js
is that possible I create one Dockerfile for this case into Production? should I run the script.sh in the Dockerfile for this case? how about the image should I use in Dockerfile? I have no idea for this case using docker because the in one code base for multiple servers running , and the problem also port of servers running
maybe one of you ever has this case? it would be great to know how to solve this problem
I am using GraphQL Federation ( Go ) for this case, so I have multiple services and Gateway ( NodeJS )
I want to deploy this into Production for this question
答案1
得分: 1
你需要四个单独的Dockerfiles,以启动四个不同程序的容器。Go组件的Dockerfiles可以相对简单:
# Dockerfile.accounts
FROM golang:1.16 AS build
WORKDIR /app
COPY . .
ARG ENV_APP=dev
RUN go build -tags "$ENV_APP" -o /accounts ./cmd/server/accounts
FROM ubuntu:20.04
COPY --from=build /accounts /usr/local/bin
CMD accounts
(如果这三个镜像除了正在构建的特定命令目录之外真的完全相同,你也可以将其作为ARG
传递进去。我假设./cmd/server/*
包需要源目录中的其他包,比如./pkg/support
,这将要求Dockerfiles位于顶级目录。)
由于你的脚本只是运行这四个程序,我通常建议使用Docker Compose来一起启动这四个容器。Compose只做“使用已知选项启动一些容器”的事情,但它可以完成你的脚本所做的一切。
# docker-compose.yml
version: '3.8'
services:
accounts:
build:
context: .
dockerfile: Dockerfile.accounts
events:
build:
context: .
dockerfile: Dockerfile.events
places:
build:
context: .
dockerfile: Dockerfile.places
gateway:
build:
context: .
dockerfile: Dockerfile.gateway
# (由于Node应用程序无法重用Go代码,这也可以合理地使用`build: cmd/gateway`和`cmd/gateway/Dockerfile`)
ports:
- 3000:3000
只需运行docker-compose up
即可在前台启动所有四个容器;一旦启动,按<kbd>Ctrl</kbd>+<kbd>C</kbd>将停止它们。你可以配置gateway使用其他容器的名称accounts
、events
、places
作为主机名;例如,http://accounts/graphql
。
你也可以按原样调整你的启动脚本。使用docker build
而不是go build
来构建镜像,使用docker run
来启动容器(可能使用固定的--name
),使用docker stop && docker rm
来停止它们。你应该使用docker network create
创建一个网络,并在它们上使用docker run --net
,以便它们可以像Compose设置一样进行通信。
英文:
You need four separate Dockerfiles for this, to launch four separate containers with four different programs. The Go component Dockerfiles can be fairly straightforward:
# Dockerfile.accounts
FROM golang:1.16 AS build
WORKDIR /app
COPY . .
ARG ENV_APP=dev
RUN go build -tags "$ENV_APP" -o /accounts ./cmd/server/accounts
FROM ubuntu:20.04
COPY --from=build /accounts /usr/local/bin
CMD accounts
(If the three images are really identical aside from the specific command directory being built, you could pass that in as an ARG
as well. I'm assuming the ./cmd/server/*
packages require packages elsewhere in your source directory like a ./pkg/support
or whatever, which would require the Dockerfiles to be at the top level.)
Since your script is just running the four programs, I'd generally recommend using Docker Compose as a way to launch the four containers together. "Launch some containers with known options" is the only thing Compose does, but it would do everything your script does.
# docker-compose.yml
version: '3.8'
services:
accounts:
build:
context: .
dockerfile: Dockerfile.accounts
events:
build:
context: .
dockerfile: Dockerfile.events
places:
build:
context: .
dockerfile: Dockerfile.places
gateway:
build:
context: .
dockerfile: Dockerfile.gateway
# (Since a Node app can't reuse Go code, this could also
# reasonably be `build: cmd/gateway` using a
# `cmd/gateway/Dockerfile`)
ports:
- 3000:3000
Just running docker-compose up
will start all four containers in the foreground; once it's up, pressing <kbd>Ctrl</kbd>+<kbd>C</kbd> will stop them all. You can configure the gateway to use the other container names accounts
, events
, places
as host names; http://accounts/graphql
for example.
You could also adapt your launcher script as-is. Run docker build
instead of go build
to build images, docker run
to start a container (probably with fixed --name
s), docker stop && docker rm
to stop them. You should docker network create
a network and docker run --net
all of the containers on them so they can communicate in the same way as the Compose setup.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论