1

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

iuer ui
  • 117
  • 9
  • It this for a local development type of scenario or are you looking to deploy these services somewhere? – Ярослав Рахматуллин Jul 10 '21 at 02:08
  • I want to deploy It into server now, maybe on GCP @ЯрославРахматуллин – iuer ui Jul 10 '21 at 02:09
  • I think you should remove the part about Apollo Gateway, because that seems like a commercial product, and does not really seem relevant to the docker question – Ярослав Рахматуллин Jul 10 '21 at 02:10
  • but the goal of this question is all about docker, also I already delete the apollo word, because my gateway running with node js @ЯрославРахматуллин – iuer ui Jul 10 '21 at 02:13
  • containers are supposed to "contain" only one service inside them. You'll need to have one container for each of your services (three containers for your go services and one for the nodejs service) and "orchestrate" them using tools like `docker-composer` on the production servers – ahmadali shafiee Jul 10 '21 at 08:26
  • is that mean I should break them into 4 services in docker-compose ?? how about dockerfiles? @ahmadalishafiee – iuer ui Jul 10 '21 at 08:33
  • you need one dockerfile for each service, which is reponsible for building the container. If you have generic way of building go applications, you can have one dockerfile for your go services and build different images using the same dockerfile – ahmadali shafiee Jul 10 '21 at 08:51
  • how about using supervisor ?? @ahmadalishafiee – iuer ui Jul 10 '21 at 09:52
  • If you're thinking about running supervisord, running the three Go applications in separate goroutines in a single process would be cleaner. – David Maze Jul 10 '21 at 10:20
  • is that any example? it might gonna work, but it might need differents port?? @DavidMaze – iuer ui Jul 10 '21 at 10:23
  • supervisord works but it's not "cloud native"y solution. because it's hard to measure different services' `liveness` and `readiness` and also scale services separately. but it's a good start – ahmadali shafiee Jul 11 '21 at 07:28

1 Answers1

1

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 Ctrl+C 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 --names), 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.

David Maze
  • 130,717
  • 29
  • 175
  • 215
  • I will try this, but is this will make our machine gonna burn ? or I need more RAM for this ?? – iuer ui Jul 10 '21 at 10:36
  • for the gateway I should change the image with node js ? right ? what does mean build: cmd/gateway on the command u create there ? – iuer ui Jul 10 '21 at 10:45
  • A Docker container isn't significantly more expensive than the single process it runs. If you're already running this in four separate processes, the resource utilization should be similar running it in four containers. – David Maze Jul 10 '21 at 10:46
  • `build: DIR_NAME` is a shorthand for `build: { context: DIR_NAME, dockerfile: Dockerfile }`. For the Go applications the Dockerfiles probably have to be in the project root directory, but since there's no code sharing you could put the Node gateway's Dockerfile into the `cmd/gateway` directory if you wanted. – David Maze Jul 10 '21 at 10:47
  • I tried to run go apps local without docker, but I tried to run gateway which node js env run in docker and list to localhost ports of the services I run locally, but it doesn't work , it said can't load services on the ports of services – iuer ui Jul 10 '21 at 14:25
  • Running the gateway in a container, but all of its dependencies outside containers, is probably the most complicated mixed-container setup; if you're going to try that, it'd be easier to use your existing script and run nothing in a container at all. But the canonical question that discusses a setup like that is [From inside of a Docker container, how do I connect to the localhost of the machine?](https://stackoverflow.com/questions/24319662/from-inside-of-a-docker-container-how-do-i-connect-to-the-localhost-of-the-mach) – David Maze Jul 10 '21 at 15:02
  • when I run all services + gateaway in containers with this link URL http://accounts/graphql, can't connect, my gateway in local run on 4000 – iuer ui Jul 10 '21 at 15:07
  • I need to expose the port , so it was solved – iuer ui Jul 10 '21 at 23:10