2

I know that a best practice of using docker is to have only one main process in each container and only one CMD line running.

My case is I have a Golang micro service and the functionality are implemented in python subprocess. Currently the main process just take API calls then invoke the python subprocess in exec and read the STDOUT and STDERR.

I want to optimize the architecture like to run python as a service (Flask) only on localhost inside docker. Then my main Golang process can use restful http call to communicate with the python process.

But that will let 2 service running in a same docker and it's not a main process and a subprocess. Will that be practically bad, Any idea?

Appreciate on all helps.

atline
  • 28,355
  • 16
  • 77
  • 113
BigTailWolf
  • 1,028
  • 6
  • 17
  • 1
    When you say optimize, what do you mean? optimize for memory, performance?.. What do you want to optimize exactly, what don't you like about the current solution? Is there a need for two languages? – jabbson Nov 25 '21 at 02:04
  • Hi @jabbson, when I mention about "optimize", it's mostly about performance. The business logic can only be implemented in python due to library dependencies and the main golang micro service is a must to use in the company. – BigTailWolf Nov 25 '21 at 03:23
  • Well, if there is a business justified necessity for having two languages, then there is not much you can do, right? Still sounds a bit odd though, to be honest. What does python subprocess calls that you cannot call from Go? Does it have to be in the same container? Could it be a separate container running the python flask app? Then your Go app would be like an API Gateway and Python container would implement a concrete backend logic? Is this something you are after? – jabbson Nov 25 '21 at 04:35
  • Well actually the company only supports us using Golang as backend language and the associated in-house framework. But the opensource solutions are all python – BigTailWolf Nov 29 '21 at 04:24

1 Answers1

2

Usually when you have multi service, the best practice is not to deploy them in one container, you are suggested to deploy them in multi containers.

You may use docker-compose to help you:

Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration.

For your scenario, give you a minimal example as next.

Folder structure:

.
├── docker-compose.yaml
├── flask
│   ├── app.py
│   └── Dockerfile
└── go
    ├── app.go
    └── Dockerfile

docker-compose.yaml:

version: '3'
services:
  flask_service:
    build: flask

  go_service:
    build: go
    ports:
    - "9500:9500"
    depends_on:
    - flask_service

go/app.go:

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
        url := "http://flask_service:9600"
        ret, err := http.Get(url)
        if err != nil {
                panic(err)
        }
        defer ret.Body.Close()

        body, err := ioutil.ReadAll(ret.Body)
        if err != nil {
                panic(err)
        }
        fmt.Fprintf(w, string(body))
}

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

go/Dockerfile:

FROM golang:latest as build

WORKDIR /go/app
COPY ./app.go .
RUN go mod init app; go mod tidy; go build

CMD ["/go/app/app"]

flask/app.py:

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hey, we have Flask in a Docker container!'

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=9600)

flask/Dockerfile:

FROM python:alpine3.7

WORKDIR /app

RUN pip install flask

COPY . /app

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

Execution:

$ docker-compose up
Creating network "20211203_default" with the default driver
Creating 20211203_flask_service_1 ... done
Creating 20211203_go_service_1    ... done
Attaching to 20211203_flask_service_1, 20211203_go_service_1

Verify:

$ curl http://10.192.244.21:9500
Hey, we have Flask in a Docker container!

You could see we visit 9500 port which will route the request to golang container, and the golang container will then call flask service container with api, and finally get the content Hey, we have Flask in a Docker container! which produced by flask.

atline
  • 28,355
  • 16
  • 77
  • 113
  • Thank you so much on the detail explanation! Maybe this is the best practice I should apply for deploying both services in same virtual machine. – BigTailWolf Dec 04 '21 at 03:27