G
G
Georgy Pugachev2020-06-29 15:51:14
Docker
Georgy Pugachev, 2020-06-29 15:51:14

How to write a Docker file for the Front+Back+DB bundle?

Hello, I have a project consisting of Front (JS+React) + Back (Go binary + config files) + DB (PostgreSQL).

Is it possible to stuff it all into a container and tie it together?
If so, are there any Dockerfile examples for such a bundle?
Do I need to integrate the PostgreSQL environment itself into this Docker file, or can only the database be integrated?
The backing binary runs on a specific port, will this binary be accessed by port from outside? I ask because if I launch several similar containers, will they conflict over ports? Or does each image need to be configured for a separate port?

Thanks to.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
D
Dmitry, 2020-06-29
@q2digger

Everything is laid out in different containers.
Separate front, separate back, separate base, separate static, etc.
Access can be painted as you like, and yes, judging by your questions - this is for freelancing. ru question.

M
Maxim Brodsky, 2020-06-29
@DeathHand

And hello to you.
Docker-compose to help you, for starters. It is rather dreary to operate with bare docker commands, and it is not required in real conditions.

Is it possible to stuff it all into a container and tie it together?

It is definitely possible to shove the whole thing into one container, but it is not necessary. How to understand what set of containers your platform will consist of? Very simple.
there is a project consisting of Front (JS + React) + Back (Go binary + config files) + DB (PostgreSQL)

Here we have decided. Your application - consists of frontend, backend and database. The names are taken solely for the sake of example, but I don't think that in the realities of developing product systems - your team lead will like the name "binarnik_na_go" instead of the name "backend" on the code review.
Do I need to integrate the PostgreSQL environment itself into this Docker file, or can only the database be integrated?

Each container contains only one application. Each container - executes only one command. If we talk about your Go binary, then the command that the backend container will execute will be the name of the binary. If this is a container with a database, then only one command will be executed in it - starting the PostgreSQL server. For the front, this will be the pm2 command, or whatever, with which you start the frontend server.
The backing binary runs on a specific port, will this binary be accessed by port from outside?

When you write your services configuration in docker-compose.yml - and docker-compose up, docker-compose will create a virtual network. The network will be named in the format <name of the directory where your docker-compose.yml is>_default. Within this network, all services will be able to access each other by the service name and port specified in EXPOSE in the service's Dockerfile. Accordingly, your backend will be available by the backend name and port that you specify when building the image. For example, http://backend:8080. However, you will not be able to access this name/port outside the virtual network. To pull the port "out", you will need to configure port binding from the backend container to the local host, this is done using the ports directive in the service description in the docker-compose.yml file.
I ask because if I run several similar containers, will they conflict over ports?

There will be no conflicts within the network. Because running multiple containers with the same name of their service is not possible. But, you can scale containers - with the help of certain commands, which at this stage it makes no sense to talk about. On the local host, respectively, pulling out two or more services on the same port will not work, for obvious reasons.
Or does each image need to be configured for a separate port?

There is no need to configure different ports, because each service has its own unique name within the container network.
To practice.
A Dockerfile for a Go backend might look like this:
# Тут берем официальный образ Golang для компиляции бинарника
# В нем есть все для сборки, за редким исключением
FROM golang:stretch as builder

# Устанавливаем рабочую директорию внутри образа сборки бинарника
WORKDIR /app

# Копируем содержимое директории с вашим проектом в образ для сборки
COPY . .

# Скачиваем зависимости
RUN go get -d -v

# Собираем бинарник в директорию /app/bin
RUN GOOS=linux GOARCH=amd64 go build -i -o bin/backend main.go

# А теперь берем минимальный образ для запуска бинарника
FROM scratch

# Из образа для сборки, копируем готовый бинарник backend-а
COPY --from=builder /app/bin/backend /app/bin/backend

# Назначаем полученный бинарник точкой входа в контейнер
ENTRYPOINT ["/app/bin/backend"]

Now, if you go to the directory with the backend project and execute:
docker build -t backend:latest .
You will have an image named backend and the latest tag. You can actually run.
Collect the image for the frontend on your own, but you'll figure it out. The essence is the same there, the first step is to take an image from node-js, build frontend in it, and use image c pm2 to launch it - by copying the directory with the application from the build step.
How your docker-compose.yml will look like:
version: "3.7"

volumes:
  database:

services:

  # Postgres. Берем готовый официальный образ
  database:
    image: postgres:12-alpine
    # Вот собственно тут и указывается, какие порты будут видны на вашей локали
    ports:
      - 5432:5432
    # Там выше в volumes указывали набор volumes. Используем вольюм database, чтобы хранить БД
    volumes:
      - database:/var/lib/postgresql/data
    restart: always

  # Backend. Берем образ, что собрали выше
  backend:
    image: backend:latest
    # В Dockerfile мы для гибкости не указывали порт backend-a. Укажем его тут. 
    expose: 
      - 8080
    ports:
      - 8080:8080
    restart: always

  # Frontend
  frontend:
    image: frontend:latest
    expose: 
      - 80
    ports:
      - 80:80
    restart: always

Actually, that's all. It remains to fix the syntax errors and run it with the docker-compose up command. By the way, there are a lot of examples of projects on the Internet with heaps of services, with separate networks for backend / frontend, with api proxying through nginx / traefik and other tricks.
Good luck.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question