Перенести проект в докер

Выполняется
Планируемый запуск: Дата начала: 03.04.2021Планируемое завершение: Дата завершения:
ПроектЗадачаСтатусДата постановкиНачалоКонецКто создал
Пивная картаПеренести проект в докерВыполняется03.04.2021 21:29:1404.04.2021 11:08:5404.04.2021 13:14:36
Пивная картаПеренести проект в докерВыполняется03.04.2021 21:29:1404.04.2021 06:18:2204.04.2021 07:24:52
Пивная картаПеренести проект в докерВыполняется03.04.2021 21:29:1404.04.2021 01:56:3104.04.2021 02:22:38
Пивная картаПеренести проект в докерВыполняется03.04.2021 21:29:1403.04.2021 21:29:2204.04.2021 01:05:42
Инструкция как запустить проект в докере.

Устанавливаем docker и docker-compose

Версии:
- docker 19.0+
- docker-compose 1.25+

Только прежде чем приступить к установке: так как у тебя диск жесткий разбит и постоянные траблы с местом на диске, сначала на большом диске (который не основной, а под всякие данные) создай папку docker и залинкуй ее на основной диск
sudo ln -s {путь к созданной папке} /var/lib/docker

Чтобы докер все образы и т.п. там хранил. А то каждый день чиститься будешь :)

Процесс установки описан здесь. Только не все ставь, а только указанное ПО. И там написано как пользователя добавить в группу docker, чтобы можно было контейнерами управлять без вызова sudo.

Запуск докер-проекта

Прежде всего, если ты с гитом все еще не работаешь через ssh, то ключ себе сделай. Вот тут описана процедура: https://docs.github.com/en/github/authenticating-to-github/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent

Плюс использования ключа в том, что тебе не придется каждый раз вводить логин/пароль там, где потребуется авторизация.

Этот же ключ можно будет использовать для доступа к серверам на digitalocaen ;-)

- Скачиваем проект
git clone --recurse-submodules https://github.com/Pivkarta/docker docker-pivkarta (или если ssh настроил, то git clone --recurse-submodules git@github.com:Pivkarta/docker.git docker-pivkarta )
cd docker-pivkarta

- Читаем readme.md, там прописаны актуальные первичные шаги. Сейчас прописано следующее:
# Copy and edit environments file cp .env.sample .env # Copy and edit web-server config file cp caddy/Caddyfile.sample caddy/Caddyfile #Copy and edit coturn config file cp coturn/turnserver.conf.sample coturn/turnserver.conf
На локальной машине можно .env и не редактировать (оставить пароли по умолчанию), но на проде конечно же надо отредактировать.

Запускаем контейнеры

Я специально в композ-файле не прописываю зависимости контейнеров, чтобы можно было на одном сервере сразу несколько проектов запускать, так что придется запускать контейнеры с явным указанием оных. Да и лучше их все прописать, чтобы было понятно что для чего.

Быстрый старт (только фронт)

Для того, чтобы быстро получить результат и в меньшие дебри лезть, запустим пока только фронт.

API_ENDPOINT=https://pivkarta.ru/api/ docker-compose -f docker-compose.yml -f docker-compose.dev.yml up --build pivkarta.ru-2

Будет довольно долго выполняться (особенно в первый раз, потому что еще надо будет ему скачать нужные докер-образы). Должно быть типа такого:

Successfully built f6ecca7db83d Successfully tagged docker-pivkarta_pivkarta.ru-2:latest Recreating docker-pivkarta_pivkarta.ru-2_1 ... done Attaching to docker-pivkarta_pivkarta.ru-2_1
Когда контейнер будет запущен, можно зайти на адрес http://localhost:3100. Должен открыться сайт. В дев-конфиге прописана линковка на исходники в локальной файловой системе, так что можно редактировать файлы в своей IDE как есть, изменения будут учитываться и в контейнере.

Если все ОК, то жмем CTRL+C, чтобы завершить выполнение программы. В этот момент у нас и контейнер остановится, потому что он работал в режиме программы. Чтобы этого не происходило, и он продолжал работать дальше, выполняем то же самое, только с флагом -d
API_ENDPOINT=https://pivkarta.ru/api/ docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build pivkarta.ru-2

Теперь, когда контейнер пересоберется (а сейчас он очень быстро это сделает, потому что никаких изменений в нем не было), команда успешно завершится и все. При этом контейнер продолжет работать. Чтобы его остановить, надо будет выполнить
docker-compose stop pivkarta.ru-2

Если надо будет удалить потом, то docker-compose rm pivkarta.ru-2

Выполнение команд внутри контейнера.

Иногда надо выполнить какую-нибудь команду в самом контейнере, например yarn generate:types.
Для этого нам надо зайти в нужный нам контейнер. Откроем еще один терминал и выполним в директории проекта docker-compose ps. Найдем в списке наш контейнер и его имя (скорее всего будет docker-pivkarta_pivkarta.ru-2_1).

Выполняем docker exec -it docker-pivkarta_pivkarta.ru-2_1 bash

Если ОК, то мы оказываемся внутри контейнера, то есть как бы в другом компьютере. Только следует учитывать, что конкретно этот образ не на базе ubuntu создан, а alpine-linux. Некоторые командыы могут отличаться (например, не apt install, а apk add). И вот, когда мы внутри, выполняем yarn generate:types.

Полный запуск (с базой данных и прочим)

MySQL
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d mysql

Расшифрую:
1. docker-compose - команда
2. -f docker-compose.yml -f docker-compose.dev.yml - указал для конфигурационных файла.
На проде надо будет -f docker-compose.yml -f docker-compose.prod.yml
3. up -d - субкоманда запуск с флагом -d - запуск в режиме демона. То есть запущенный контейнер будет крутиться как служба, то есть терминал сразу освобождается и его можно будет даже закрыть.

Проверим работу контейнера.

docker-compose ps

Должно быть типа такого:

$ docker-compose ps
Name Command State Ports
-------------------------------------------------------------------------------------------------
docker-pivkarta_mysql_1 docker-entrypoint.sh mysqld Up 0.0.0.0:3306->3306/tcp, 33060/tcp

Здесь видно, что контейнер с персональным именем docker-pivkarta_mysql_1 работает (State Up) и открыт внешний порт 3306 указывающий на внутренний 3306 (0.0.0.0:3306->3306/tcp), а так же работает внутренний 33060.

То есть все как и ожидалось.

4. имя службы (service).
Все службы и их конфигурации прописаны в docker-compose.yml. Дополнительные файлы типа docker-compose.dev.yml содеражат переопределяющие конфиги для этих служб (не обязательно для всех).

PhpMyAdmin
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d pma

Закрепим материал и еще раз выполним docker-compose ps
Видим:
$ docker-compose ps
Name Command State Ports
----------------------------------------------------------------------------------------------------
docker-pivkarta_mysql_1 docker-entrypoint.sh mysqld Up 0.0.0.0:3306->3306/tcp, 33060/tcp
docker-pivkarta_pma_1 /docker-entrypoint.sh apac ... Up 0.0.0.0:8090->80/tcp

У нас уже два работающих контейнера. Обрати внимание, что у pma внешний и внутренний порты отличаются. Это не страшно. Это как раз фишка докера - можно запустить несколько сервисов, каждый из которых используют один и тот же порт, но указать им разные, чтобы они не конфликтовали. То есть хотя PhpMyAdmin в контейнере и крутится на порту 80, для доступа к нему мы используем адрес http://localhost:8090

Откроем этот адрес в браузере и увидим привычный PhpMyAdmin. Если пароль в .env не менял, то используем указанные по умолчанию логин/пароль: root/prisma

Инспектирование контейнеров

Вот здесь важно сразу понять что за что отвечает.

docker-compose - это всего лишь утилита оркестрации докер-контейнеров. При чем ее даже не рекомендуют использовать в продакшене, типа есть более правильные инструменты (но я их пока не освоил). Само же ядро этой системы - сам docker. То есть все команды так или иначе выполняются через docker. Просто в докере одна команда - один контейнер (ну, кроме типа docker ps, который выводит список контейнеров). А docker-compose создан, чтобы управлять проектами. При этом проекты могут содержать и по одному контейнеру, не обязательно несколько. Суть просто в том, что создается папка с файлом docker-compose.yml, в котором прописано все необходимое для запуска, и когда мы запускаем из этой папки через docker-compose, последний берет на себя работу по неймингу конечных контейнеров (как у нас получился docker-pivkarta_mysql_1, а не просто mysql), быстрому доступу к контейнерам именно этого проекта и т.п. Без этого, запустив через сам docker из разных проектов кучу контейнеров, нам сложно будет ориентироваться какой контейнер к чему относится. То есть если мы выполним docker ps, то мы увидим все запущенные на этом сервере контейнеры. А выполнив docker-compose ps в папке проекта, мы увидим только те контейнеры, которые относятся конкретно к этому проекту. К примеру, если мы захотим остановить все контейнеры текущего проекта, мы выполним docker-compose stop. А с чистым докером нам пришлось бы явно перечислять контейнеры (или использовать хитрости с фильтрацией, тегами).

Но docker-compose не все команды поддерживает. К примеру нельзя выполнить docker-compose inspect pma. А нам нужна именно эта команда. Поэтому мы обратимся к докеру напрямую docker inspect docker-pivkarta_pma_1

Здесь следует отметить, что в docker-compose мы оперируем именами сервисов, а в docker именами контейнеров, поэтому используем docker-pivkarta_pma_1, а не pma.

Команда inspect покажет нам много полезной информации, в том числе из какого образа контейнер собран, с какими параметрами, какие виртуальные диски подключены и т.п. Нам же сейчас надо просто посмотреть какой ip задан этому контейнеру. Вот эта информация (может конечно же отличаться на вашей машине):

"NetworkSettings": { "Bridge": "", "SandboxID": "56210129d737e6c1c17ed9b6e87eb073ff9044aa567adb3c70c11d5717a103e5", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": { "80/tcp": [ { "HostIp": "0.0.0.0", "HostPort": "8090" } ] }, "SandboxKey": "/var/run/docker/netns/56210129d737", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "", "Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "", "IPPrefixLen": 0, "IPv6Gateway": "", "MacAddress": "", "Networks": { "pivkarta-default": { "IPAMConfig": null, "Links": null, "Aliases": [ "090faba4fdd5", "pma" ], "NetworkID": "cc2dd7dc6b30478229053bec043bce80801020ddfd87b4dbf6472413d6bf1fc5", "EndpointID": "6194e69e837d55cf2717683e3201b8e982eb2db3a46724b302935110ac4b0ffd", "Gateway": "172.16.6.1", "IPAddress": "172.16.6.2", "IPPrefixLen": 24, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:10:06:02", "DriverOpts": null } } }
И здесь самая главная для нас информация - "IPAddress": "172.16.6.2", а так же Ports, где видно, что 80-му порту соответствует 8090

То есть контейнеру задан ip 172.16.6.2. А значит мы можем к его внутренним адресам обращаться напрямую по этому адресу. Откроем в браузере http://172.16.6.2 (то есть именно с 80 портом, а не внешним 8090) и увидим, что нам так же откроется PhpMyAdmin. Сейчас смысл всего этого наверняка покажется неочевидным, но просто помни, что здесь эта инфа есть, и она наверняка еще пригодится.

Prisma-сервер

docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build prisma

В дев-режиме будет крутиться на порту 4466

API-сервер

docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build api

После успеешного запуска (который включает в себя в том числе и деплой схемы в призма-сервер), можно увидеть призма-АПИ, который админский и который не должен быть виден напрямую на прод-сервере. С этим призма-АПИ и работает фронтовый АПИ-сервер. Смотри эндпоинты в .env файле. У тебя их там два (обнови репу докера, я там фикс вылил, и у себя .env поправь):
dev_endpoint=http://prisma:4466/pivkarta/dev prod_endpoint=http://prisma:4466/pivkarta/prod

Соответственно, если ты АПИ-сервер запускаешь в дев-режиме (или в данном случае правильней сказать не в прод-режиме, потому что только в docker-compose.prod.yml прописано endpoint=${prod_endpoint}), то у тебя призма-АПИ и открывается по адресу http://prisma:4466/pivkarta/dev. Если ты изменишь переменные и пересоберешь АПИ-сервер, то и призма-АПИ заработают на новом адресе (но старые просто так никуда не удалятся).

В базе данных имена баз данных будут со знаками @ вместо /, то есть pivkarta@dev и pivkarta@prod. После первого деплоя надо сделать следующее:
1. Снять актуальный дамп с боевого сайта.
2. В целевой базе призмы удалить вообще все таблицы.
3. Залить дамп базы.

Все, это надо сделать разово. Просто у твоего сайта есть таблицы, про которые призма ничего не знает. И данные она не заливает, а только схему.

proxy-сервер

docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build proxy

Конфигурация прокси-сервера прописана в caddy/Caddyfile

Пример отдельного хоста:
0.0.0.0:2016 { tls off gzip proxy / api:4000 { transparent websocket } }
То есть запросы на порт 2016 будут проксироваться на api-сервер на порт 4000. В данном случае не важно открыт порт 4000 у api-сервера или нет (вспоминаем написанное выше про внешние и внутренние порты). То есть даже если 4000 порт у него не открыт и нельзя зайти на http://localhost:4000, все равно, когда мы заходим на http://localhost:2016, мы попадаем на http://api:4000

Николай, уперся - таки:

dima@dima-Lenovo-ideapad-720-15IKB:~/docker/docker-pivkarta$ API_ENDPOINT=https://pivkarta.ru/api/ docker-compose -f docker-compose.yml -f docker-compose.dev.yml up --build pivkarta.ru-2
Building pivkarta.ru-2
ERROR: Cannot locate specified Dockerfile: ./pivkarta.ru-2/Dockerfile

Пробовал sudo docker-compose up -d

Таки собрался и запустился контейнер, но:
Prisma server is unavailable - sleeping
Prisma server is unavailable - sleeping
Prisma server is unavailable - sleeping
...
Prisma server is unavailable - sleeping


Не подскажешь, в чем может быть проблемка?
Дима, мой косяк. Я написал в инструкции
git clone https://github.com/Pivkarta/docker docker-pivkarta

а надо
git clone --recurse-submodules https://github.com/Pivkarta/docker docker-pivkarta

иначе он не скачивает субмодули.

ls -la prisma-cms/pivkarta.ru
пусто?
В общем в такой ситуации проще всего удалить проект и склонировать по новой правильно.
Но можно попробовать так:
git submodule init
git pull --recurse-submodules
Все прошло нормально: сайт и phpMyAdmin увидел!


При попытке запустить API

API-сервер
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build api
Prisma server is unavailable - sleeping
Prisma server is unavailable - sleeping
Prisma server is unavailable - sleeping
Prisma server is unavailable - sleeping
Prisma server is unavailable - sleeping
Prisma server is unavailable - sleeping
...
Prisma server is unavailable - sleeping

А вот прокси нормально сформировался.
Просто я не дописал еще полную версию :) Сейчас дописал. Надо было просто еще prisma-сервис запустить. Ну и дописал как дамп базы перенести. Делай, раз быстрый старт прошел.
Сунулся проверять , работают ли контейнеры, а то не отдаётся ничего по http://localhost:3100

dima@dima-Lenovo-ideapad-720-15IKB:~/docker/docker-pivkarta$ docker-compose ps
Name Command State Ports
---------------------------------------------------------------------------------
docker-pivkarta_mysql_1 docker-entrypoint.sh mysqld Exit 0
docker-pivkarta_pivkarta.ru-2_1 bash -c yarn dev Exit 1
docker-pivkarta_pma_1 /docker-entrypoint.sh apac ... Exit 0
docker-pivkarta_proxy_1 /bin/parent caddy --conf / ... Exit 0

На контейнере сайта Exit 1: это хорошо или плохо?

docker logs docker-pivkarta_pivkarta.ru-2_1

--------------------------
yarn run v1.22.10
$ cross-env NODE_ENV=development TS_NODE_PROJECT=tsconfig.server.json ts-node-dev --ignore-watch .next --rs --no-notify --respawn --transpile-only server
[INFO] 13:12:04 ts-node-dev ver. 1.1.6 (using ts-node ver. 9.1.1, typescript ver. 4.2.3)
[HPM] Proxy created: / -> https://pivkarta.ru/api/
[HPM] Proxy rewrite rule created: "^/api(/|$)" ~> "/"
info - automatically enabled Fast Refresh for 1 custom loader
info - Using external babel configuration from /www/pivkarta.ru-2/.babelrc
[BABEL] Note: The code generator has deoptimised the styling of /www/pivkarta.ru-2/src/modules/gql/generated/types.ts as it exceeds the max of 500KB.
[BABEL] Note: The code generator has deoptimised the styling of /www/pivkarta.ru-2/src/modules/gql/generated/types.ts as it exceeds the max of 500KB.
event - compiled successfully
Attention: Next.js now collects completely anonymous telemetry regarding usage.
This information is used to shape Next.js' roadmap and prioritize features.
You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the following URL:
https://nextjs.org/telemetry

> Ready on http://localhost:3000
event - build page: /
wait - compiling...
event - compiled successfully
event - build page: /city
wait - compiling...
event - compiled successfully
yarn run v1.22.10
$ cross-env NODE_ENV=development TS_NODE_PROJECT=tsconfig.server.json ts-node-dev --ignore-watch .next --rs --no-notify --respawn --transpile-only server
[INFO] 13:46:26 ts-node-dev ver. 1.1.6 (using ts-node ver. 9.1.1, typescript ver. 4.2.3)
[HPM] Proxy created: / -> https://pivkarta.ru/api/
[HPM] Proxy rewrite rule created: "^/api(/|$)" ~> "/"
info - automatically enabled Fast Refresh for 1 custom loader
info - Using external babel configuration from /www/pivkarta.ru-2/.babelrc
event - compiled successfully
> Ready on http://localhost:3000
event - build page: /city
wait - compiling...
event - compiled successfully
event - build page: /404
wait - compiling...
event - compiled successfully

-------------------------

Ответ нашелся)

docker-compose start pivkarta.ru-2

Вопрос для верности: сам же сайт правим в docker-pivkarta/prisma-cms/pivkarta.ru-2 ?

>> Вопрос для верности: сам же сайт правим в docker-pivkarta/prisma-cms/pivkarta.ru-2 ?
Да, все верно.
На контейнере сайта Exit 1: это хорошо или плохо?
Это плохо. Значит ошибка возникла непредвиденная.
0 - это ОК, то есть тоже exit, но одидаемый, то есть это успешное выполнение программы и выход из нее.

Можешь логи посмотреть контейнера.
docker-compose logs pivkarta.ru-2
или docker logs docker-pivkarta_pivkarta.ru-2_1

Только не docker-compose start pivkarta.ru-2, а
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build pivkarta.ru-2
>>
Можешь логи посмотреть контейнера.
docker-compose logs pivkarta.ru-2
или docker logs docker-pivkarta_pivkarta.ru-2_1


Логи выше кинул.


>>
Только не docker-compose start pivkarta.ru-2, а
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build pivkarta.ru-2

То есть мы заново формируем контейнер ,а не запускаем старый?

>> То есть мы заново формируем контейнер ,а не запускаем старый?
Если ничего не поменялось в исходниках контейнера, то он ничего не будет пересобирать. Для этого придется сделать docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build --force-recreate pivkarta.ru-2

Но в docker-compose.dev.yml есть дополнительные настройки контейнера, которые не были применены, когда ты запустил контейнер без указания этого файла, поэтому надо по новой запустить. Нельзя просто так перезапустить имеющийся контейнер с новыми конфиг-файлами.
Николай, опять странная засада:
выполняю
Prisma-сервер
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build prisma
В дев-режиме будет крутиться на порту 4466

Контейнер работает:
docker- docker-entrypoint.sh Exit 0
pivkarta_mysql_1 mysqld
docker-pivkarta_pivkar bash -c yarn dev Up 0.0.0.0:3100->3000/tc
ta.ru-2_1 p
docker-pivkarta_pma_1 /docker-entrypoint.sh Exit 0
apac ...
docker- /bin/sh -c Up 0.0.0.0:4466->4466/tc
pivkarta_prisma_1 /app/start.sh p
docker- /bin/parent caddy Exit 0


И сразу
docker- /bin/sh -c Exit 1
pivkarta_prisma_1 /app/start.sh

Лог выдает такой:

Exception in thread "main" java.sql.SQLTransientConnectionException: database - Connection is not available, request timed out after 5000ms.
at com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:548)
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:186)
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:145)
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:83)
at slick.jdbc.hikaricp.HikariCPJdbcDataSource.createConnection(HikariCPJdbcDataSource.scala:14)
at slick.jdbc.JdbcBackend$BaseSession.<init>(JdbcBackend.scala:453)
at slick.jdbc.JdbcBackend$DatabaseDef.createSession(JdbcBackend.scala:46)
at slick.jdbc.JdbcBackend$DatabaseDef.createSession(JdbcBackend.scala:37)
at slick.basic.BasicBackend$DatabaseDef.acquireSession(BasicBackend.scala:249)
at slick.basic.BasicBackend$DatabaseDef.acquireSession$(BasicBackend.scala:248)
at slick.jdbc.JdbcBackend$DatabaseDef.acquireSession(JdbcBackend.scala:37)
at slick.basic.BasicBackend$DatabaseDef$$anon$2.run(BasicBackend.scala:274)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.sql.SQLNonTransientConnectionException: Could not connect to address=(host=mysql)(port=3306)(type=master) : mysql
at org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper.get(ExceptionMapper.java:161)
at org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper.connException(ExceptionMapper.java:79)
at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.connectWithoutProxy(AbstractConnectProtocol.java:1040)
at org.mariadb.jdbc.internal.util.Utils.retrieveProxy(Utils.java:490)
at org.mariadb.jdbc.MariaDbConnection.newConnection(MariaDbConnection.java:144)
at org.mariadb.jdbc.Driver.connect(Driver.java:90)
at slick.jdbc.DriverDataSource.getConnection(DriverDataSource.scala:101)
at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:341)
at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:193)
at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:430)
at com.zaxxer.hikari.pool.HikariPool.access$500(HikariPool.java:64)
at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:570)
at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:563)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
... 3 more
Caused by: java.net.UnknownHostException: mysql
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:184)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at java.net.Socket.connect(Socket.java:538)
at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.connect(AbstractConnectProtocol.java:398)
at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.connectWithoutProxy(AbstractConnectProtocol.java:1032)
... 14 more
Exception in thread "main" java.sql.SQLTransientConnectionException: database - Connection is not available, request timed out after 5000ms.
at com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:548)
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:186)
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:145)
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:83)
at slick.jdbc.hikaricp.HikariCPJdbcDataSource.createConnection(HikariCPJdbcDataSource.scala:14)
at slick.jdbc.JdbcBackend$BaseSession.<init>(JdbcBackend.scala:453)
at slick.jdbc.JdbcBackend$DatabaseDef.createSession(JdbcBackend.scala:46)
at slick.jdbc.JdbcBackend$DatabaseDef.createSession(JdbcBackend.scala:37)
at slick.basic.BasicBackend$DatabaseDef.acquireSession(BasicBackend.scala:249)
at slick.basic.BasicBackend$DatabaseDef.acquireSession$(BasicBackend.scala:248)
at slick.jdbc.JdbcBackend$DatabaseDef.acquireSession(JdbcBackend.scala:37)
at slick.basic.BasicBackend$DatabaseDef$$anon$2.run(BasicBackend.scala:274)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.sql.SQLNonTransientConnectionException: Could not connect to address=(host=mysql)(port=3306)(type=master) : mysql
at org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper.get(ExceptionMapper.java:161)
at org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper.connException(ExceptionMapper.java:79)
at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.connectWithoutProxy(AbstractConnectProtocol.java:1040)
at org.mariadb.jdbc.internal.util.Utils.retrieveProxy(Utils.java:490)
at org.mariadb.jdbc.MariaDbConnection.newConnection(MariaDbConnection.java:144)
at org.mariadb.jdbc.Driver.connect(Driver.java:90)
at slick.jdbc.DriverDataSource.getConnection(DriverDataSource.scala:101)
at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:341)
at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:193)
at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:430)
at com.zaxxer.hikari.pool.HikariPool.access$500(HikariPool.java:64)
at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:570)
at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:563)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
... 3 more
Caused by: java.net.UnknownHostException: mysql
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:184)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at java.net.Socket.connect(Socket.java:538)
at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.connect(AbstractConnectProtocol.java:398)
at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.connectWithoutProxy(AbstractConnectProtocol.java:1032)
... 14 more
Exception in thread "main" java.sql.SQLTransientConnectionException: database - Connection is not available, request timed out after 5000ms.
at com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:548)
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:186)
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:145)
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:83)
at slick.jdbc.hikaricp.HikariCPJdbcDataSource.createConnection(HikariCPJdbcDataSource.scala:14)
at slick.jdbc.JdbcBackend$BaseSession.<init>(JdbcBackend.scala:453)
at slick.jdbc.JdbcBackend$DatabaseDef.createSession(JdbcBackend.scala:46)
at slick.jdbc.JdbcBackend$DatabaseDef.createSession(JdbcBackend.scala:37)
at slick.basic.BasicBackend$DatabaseDef.acquireSession(BasicBackend.scala:249)
at slick.basic.BasicBackend$DatabaseDef.acquireSession$(BasicBackend.scala:248)
at slick.jdbc.JdbcBackend$DatabaseDef.acquireSession(JdbcBackend.scala:37)
at slick.basic.BasicBackend$DatabaseDef$$anon$2.run(BasicBackend.scala:274)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.sql.SQLNonTransientConnectionException: Could not connect to address=(host=mysql)(port=3306)(type=master) : mysql
at org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper.get(ExceptionMapper.java:161)
at org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper.connException(ExceptionMapper.java:79)
at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.connectWithoutProxy(AbstractConnectProtocol.java:1040)
at org.mariadb.jdbc.internal.util.Utils.retrieveProxy(Utils.java:490)
at org.mariadb.jdbc.MariaDbConnection.newConnection(MariaDbConnection.java:144)
at org.mariadb.jdbc.Driver.connect(Driver.java:90)
at slick.jdbc.DriverDataSource.getConnection(DriverDataSource.scala:101)
at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:341)
at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:193)
at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:430)
at com.zaxxer.hikari.pool.HikariPool.access$500(HikariPool.java:64)
at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:570)
at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:563)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
... 3 more
Caused by: java.net.UnknownHostException: mysql
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:184)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at java.net.Socket.connect(Socket.java:538)
at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.connect(AbstractConnectProtocol.java:398)
at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.connectWithoutProxy(AbstractConnectProtocol.java:1032)
... 14 more

>> Контейнер работает:
docker- docker-entrypoint.sh Exit 0
pivkarta_mysql_1 mysqld

Дима, еще раз: Exit - это не работает, это завершил работу. Up - это вот работает.
docker-compose ps показывает не список работающих контейнеров, а просто список контейнеров.

У тебя все контейнеры не работают (вероятнее всего ты перезагружался или типа того). В прод-конфиге прописано restart: always. Вот когда контейнер собран с таким параметром, вот тогда он каждый раз пытается опять запуститься, даже если процесс завершился непредвиденно.

Тебе пишет ошибки:

- Exception in thread "main" java.sql.SQLTransientConnectionException: database - Connection is not available, request timed out after 5000ms.
То есть не удалось связаться с базой данных за отведенные 5 секунд.

- Caused by: java.sql.SQLNonTransientConnectionException: Could not connect to address=(host=mysql)(port=3306)(type=master) : mysql
Просто факт: не удалось связаться с базой данных

- Caused by: java.net.UnknownHostException: mysql
А вот это уже причина: не известный хост mysql. То есть призма просто не знала по какому адресу находится база данных. А не знала потому что контейнер не запущен и докер в своей сети не выделил ему хост. Это же все внутренние хосты.

Решение: перезапусти все контейнеры разом.
docker-compose restart

Скорее всего это поможет, так как у тебя контейнеры все уже собраны, просто не запущены. Но есть небольшая вероятность, что призма все-таки не запустится (хотя вероятность мааленькая). После рестарта проверь контейнеры docker-compose ps. Если призма так же Exit 1, но другие контейнеры работают, просто опять ее собери или даже просто рестартани конкретно ее docker-compose restart prisma, но скорее всего это не потребуется.


Николай, я не тот контейнер прислал( Там был Up на 4466!
Но в целом понял: только контейнер с сайтом поднимается сам, а для всего остального нужен комплекс контейнеров.

Спасибо!!

Можешь напомнить ,какой плагин к vs для подсвечивания ошибок TS используем? Eslint поставил, а вот чем TS проверяем - не могу найти: видео пересматривать сел)
>> Но в целом понял: только контейнер с сайтом поднимается сам, а для всего остального нужен комплекс контейнеров.
Это надо смотреть индивидуально. Смотри, когда мы запускаем
API_ENDPOINT=https://pivkarta.ru/api/ docker-compose -f docker-compose.yml -f docker-compose.dev.yml up --build pivkarta.ru-2
то API запросы будут лететь на https://pivkarta.ru/api/, то есть да, в таком случае ему нужно только чтобы сайт https://pivkarta.ru был доступен.

Альтернативно можно API_ENDPOINT=https://pivkarta.ru/api/ прописать в .env и запускать как обычно
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up --build pivkarta.ru-2

Просто в .env пишутся переменные окружения по умолчанию, но их можно переопределить, прописав в начале выполнения команды.

Так вот, если у тебя будет прописано типа API_ENDPOINT=http://api:4000, то тогда уже запросы будут лететь на этот сервер, а не внешний pivkarta.ru, то есть у тебя должен быть запущен контейнер api. А api куда запросы шлет? На prisma. А prisma что для себя требует? Откуда данные берет? mysql. Вот тебе и цепочка. Как минимум эти контейнеры ты должен запустить для работы.

А еще в mysql заглянуть надо? - pma запускаешь.

Но в дев-режиме-то у нас порты открыты, а в прод - нет. То есть просто так не достучишься. Значит что нам нужно? Прокси-сервер. А это уже proxy. Помнишь в начале инструкции писал? cp caddy/Caddyfile.sample caddy/Caddyfile

Вот посмотри этот сампл. Пример

0.0.0.0:2016 { tls off gzip # log / stdout "API: {upstream} {combined} UPSTREAM: {upstream} REWRITE: {rewrite_uri} TOKEN: {>X-App-Token} COOKIE:{~AppSession}\n" proxy / api:4000 { transparent websocket } }
Ничего не узнаешь?

То есть если прокси запустишь, http://localhost:2016 - это будет API. http://localhost:2015 - фронт. http://localhost:2017 - PhpMyAdmin.

Вот, и уже ты локальный хостинг-провайдер )))

Это надо как-то утрамбовать в понимании)
Все логично, но требуется потыкать пальцем))
Потому и подаю постепенно, от малого к большему. Но утрамбуется. Просто представь, что у тебя на компе теперь несколько отдельных компьютеров и они между собой взаимодействуют.
У меня и так уже 2 убунты и одна винда))) Плюс ещё контейнеры))))
Интересно, когда железка ляжет...

Не скоро :) Ты же не одновременно все это запускаешь.

Добавить комментарий