Связать контейнеры с фронтендом и бэкендом
Решил простую задачку. Использовал БД Postgres, на бэкенде Spring Boot, фронтенд на AngularJS. Сейчас пытаюсь всё это упаковать в 3 контейнера чтобы развернуть потом на виртуалке. Вот тут с Докером у меня проблемы. Файл docker-compose.yaml такой:
version: '3.0'
services:
pgdb:
build:
context: services/database
dockerfile: Dockerfile
image: 'image_db'
container_name: 'container_db'
ports:
- 15433:5432 # Чтобы подключиться к БД с хоста
environment:
- 'POSTGRES_DB=db1'
- 'POSTGRES_USER=user1'
- 'POSTGRES_PASSWORD=pswd1'
volumes:
- pgdata:/var/lib/postgresql/data
back:
build:
context: services/backend
dockerfile: Dockerfile
image: 'image_back'
container_name: 'container_back'
environment:
- 'SPRING_DATASOURCE_URL=jdbc:postgresql://pgdb:5432/db1'
depends_on:
- pgdb
front:
build:
context: services/frontend
dockerfile: Dockerfile
image: 'image_front'
container_name: 'container_front'
ports:
- 8099:80
volumes:
pgdata:
Сервис 'pgdb': здесь я указал проброс портов
- 15433:5432чтобы можно было с хоста подключиться к БД и посмотреть данные в таблицах.Сервис 'back': тут я указываю переменную окружения
'SPRING_DATASOURCE_URL=jdbc:postgresql://pgdb:5432/db1'в которой написано pgdb:5432 то есть название сервиса с базой данных, чтобы он подключился к этому контейнеру. Также в самом коде бэкенда в файле application.yaml у меня прописаны url/логин/пароль от БД, и на каком порту стартует бэкенд:
server:
port: 8083
- Сервис 'front': в его Dockerfile я указал родительский образ nginx и добавляю туда папку html с файлами фронтенда:
FROM nginx
WORKDIR /usr/share/nginx/html
COPY html .
Я так понимаю nginx внутри контейнера стартует на порту 80, поэтому я добавил проброс портов - 8099:80 чтобы на хост машине открывать в браузере localhost:8099 и попадать в контейнер с фронтендом.
А также в файле .js у меня указан url для бэкенда apiPath = localhost:8083 , так как бэкенд как раз на порту 8083 запущен.
Я везде использую разные значения для портов намеренно, чтобы разобраться как это всё работает.
Вроде если я правильно понимаю сейчас моя схема вот такая:

Фронтенд внутри своего контейнера будет обращаться на свой внутренний localhost:8083 Собственно это как раз тот момент, который я не пойму как сделать. Надо как-то сказать контейнеру с фронтом , что надо стучаться в localhost:8083 который внутри бэкендовского контейнера.
Но если запустить docker-compose.yaml так как есть сейчас, то ожидаемо не работает. Я открываю на самом компе адрес localhost:8099 , попадаю в контейнер с фронтендом и вижу там запущенный фронтенд, но там только вёрстка, никаких данных нет, так как он долбится внутри своего контейнера, а не в контейнер с бэкендом.
Но при этом если сделать в консоли команду docker network ls то я вижу что появилась сеть с именем prod_default ('prod' это название папки внутри которой файл docker-compose.yaml лежит). И если посмотреть сеть командой
docker network inspect prod_default то вижу такое:
[
{
"Name": "prod_default",
"Id": "fa63163cd8c2637746e65e7504782461abca065a7fe51ebf458c12cb525fe577",
"Created": "2022-12-02T02:47:00.354470961+07:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.22.0.0/16",
"Gateway": "172.22.0.1"
}
]
},
"Internal": false,
"Attachable": true,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"77b45daf889b0cbb06a2842efc0722c9505b191c27ce6792bd3483377ac9d069": {
"Name": "container_back",
"EndpointID": "cfe28da474636bdc4f7c85edbd3369232f6362254db3730503489f7978b79274",
"MacAddress": "02:42:ac:16:00:04",
"IPv4Address": "172.22.0.4/16",
"IPv6Address": ""
},
"bf55e093b29959cb2c5418ca3d532b00aec04f161381ed1c528b7e0657f2e957": {
"Name": "container_front",
"EndpointID": "5e03aedb5786f59bf76b7d806fc525cf0eb5df4a28b03aa9c32ec6319e9ceb9b",
"MacAddress": "02:42:ac:16:00:02",
"IPv4Address": "172.22.0.2/16",
"IPv6Address": ""
},
"debfe3a6eeccdcb8b3a88f5cfe9c533b6c6da79a0d6109e31d68c0276721d25a": {
"Name": "container_db",
"EndpointID": "ece93f0546c71eaf38a0a49d3ddee046cf72b150c64d272631ed295a974a4281",
"MacAddress": "02:42:ac:16:00:03",
"IPv4Address": "172.22.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {
"com.docker.compose.network": "default",
"com.docker.compose.project": "prod",
"com.docker.compose.version": "1.21.2"
}
}
]
То есть получается при запуске docker-compose создалась некая дефолтная сеть, хотя я нигде и не прописывал её. И там видно раздел "Containers" где все 3 контейнера и перечислены. Но если они по умолчанию попадают в некую дефолтную сеть, странно тогда что контейнер с фронтом не видит контейнер с бекендом.
В общем, подскажите плиз как связать эти 2 контейнера? :-))
Ответы (1 шт):
Все же лучше побольше ознакомиться с документацией, но вкратце примерно так:
- сеть типа brige создается автоматически при запуске Докера, но её не стоит использовать для общения между контейнерами.
- для общения между контейнерами вам нужна пользовательская сеть докер, к которой будет подключены ваши контейнеры. И в "собственной сети" контейнерам нужно задавать имена. Грубо говоря хотя бы потому, что вы не можете гарантировать фиксированный IP контейнера в сети докер при перезапуске
- соединение вашего фронта с бэкендом и бекенда с базой это никак не localhost, это обращение к другому контейнеру (узлу) в пользовательской сети
- вот не советую прокидывать порты во все контейнеры в лоб. Нормальный вариант (имхо) когда с хост машины прокинут порт в (условный) nginx в контейнере, а контейнеры базы и бэкенда могут быть доступны с хост машины, а не снаружи. Ну т.е. указать проброс порта в контейнер БД/бэкенда, как проброс 127.0.0.1:<порт хоста>:<порт сервиса в контейнере>