Недавно писал серию статей о том, как я сделал java-приложение с сервлетами, Jsp страницами и MySQL базой. Теперь решил попробовать загрузить его в интернет.
Сначала рассматривал сервис render, но потом остановился на railway, так как на рендере поддерживалась база PostgreSQL, а я не хотел ничего менять и просто хотел попробовать залить всё как есть в сеть.
Для этого дельца требуется
- готовый war-файл в папке target
- залитый на github проект (target я исключил из gitignore, чтобы war туда тоже загрузился)
- дамп sql-базы (у меня это три sql-файла: по одному на каждую табличку)
- DockerFile с Tomcat.
Так как первые три пункта у меня выполнены, перейду к четвёртому.
Создание DockerFile
В папке проекта я создал DockerFile (без расширения) со следующим содержимым:
FROM tomcat:9.0.85-jdk11-temurin
RUN rm -rf /usr/local/tomcat/webapps/*
COPY target/TopChart-1.0-SNAPSHOT.war /usr/local/tomcat/webapps/ROOT.war
EXPOSE 8080
CMD ["/usr/local/tomcat/bin/catalina.sh", "run"]
В этом коде я использую официальный образ Tomcat с Java 11.
Потом удаляю все приложения tomcat.
Потом копирую свой war-файл по имени TopChart-1.0-SNAPSHOT.war в томкат уже с новым именем ROOT.war
И открываю порт 8080, чтобы по нему потом открыть приложение.
Добавление проекта с github на railway
Первым делом, конечно, нужно зарегистрироваться на railway (я регистрировался через github). Поначалу сервис бесплатный, и можно его потестить месяц.
Далее выбираем New — Project, подключаемся к гитхабу и ищем в списке нужный проект.

После этого проект некоторое время будет деплоиться. Как только процесс закончится, он появится в списке Deployments с сообщением Deployment Successful.

Поначалу видим сообщение Unexposed service. То есть пока что он не подключён к публичному URL. Чтобы это поправить, заходим в настройки (вкладка Settings), находим там Public Network, выбираем порт 8080, который мы указали в докере и нажимаем Generate Domain.

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

Если это не срабатывает (хоть вроде мы явно указали порт в докере), то можно попробовать добавить в корень проекта файл railway.json:
{
"build": {
"dockerfilePath": "Dockerfile"
},
"deploy": {
"startCommand": "catalina.sh run",
"restartPolicyType": "ON_FAILURE"
},
"ports": [
{
"port": 8080,
"healthcheckPath": "/",
"protocol": "HTTP"
}
]
}
Не знаю, насколько это важный шаг, но именно после него у меня всё заработало. Я добавил файл, закомиттил изменения в гит, запушил их, и проект автоматически обновился. После этого мне удалось получить адрес. Он появился вместо Unexposed сообщения:

Теперь мы можем делиться ссылкой с другими людьми, пушить в гитхаб изменения и они автоматически будут подгружаться в проект. Но для начала лучше добавить базу, чтобы проект работал.
Добавление MySQL базы в railway проект и перенос дампов с локальной машины
Теперь можем добавить базу данных. Выходим из проекта и нажимаем на кнопку Create. В окне выбираем базу данных. Так как у меня MySQL база, то я выбираю соответствующий пункт. Сервис поддерживает и другие варианты.

Заходим в базу. Пока что она пустая. Можно конечно создать таблички и наполнить их прям здесь, но я всё же загружу свои дампы. Для этого нужно зайти в Connect.

Но перед этим изучим вкладку Variables, где мы увидим все ценные данные, вроде пароля, пользователя и т.д.

Пароль нужен будет для подключения к базе, когда мы будем заливать в неё наши данные.
Далее вернёмся к Connect. В окне во вкладе Public Network мы увидим ссылку на базу. Так к ней можно будет подключиться извне.

Нас интересует Connection URL. Здесь видим следующую информацию:
- хост: interchange.proxy.rlwy.net
- порт: 10144
- название базы: railway
- юзер: root
Из этого можно собрать команду MySQL для загрузки данных, но это уже учтиво сделано самим сервисом. Во второй строчке видим mysql command.
Но как собрать её самим? Пишем mysql (если адрес прописан в переменных среды в PATH) или адрес к mysql.exe (как у меня). После -h указывает хост, после -P номер порта, после -u название юзера, после -p пароль (БЕЗ ПРОБЕЛОВ между -p и паролем), а потом через пробел название базы.
Вбивать пароль в командную строку может быть небезопасно, поэтому после -p можно будет его не вставлять, но тогда придётся вводить вручную. На изображении оба варианта: в первом случае пароль указан сразу в строке, во втором он пишется по запросу.

Я использую следующие строчки для загрузки своих файлов:
"C:\Program Files\MySQL\MySQL Server 8.0\bin\mysql.exe" -h interchange.proxy.rlwy.net -P 10144 -u root -p railway < top40_app_song.sql
"C:\Program Files\MySQL\MySQL Server 8.0\bin\mysql.exe" -h interchange.proxy.rlwy.net -P 10144 -u root -p railway < top40_app_chart.sql
"C:\Program Files\MySQL\MySQL Server 8.0\bin\mysql.exe" -h interchange.proxy.rlwy.net -P 10144 -u root -p railway < top40_app_position.sql
После каждой такой строчки меня просят ввести пароль, что я и делаю, но не всегда успешно с первого раза)))
В итоге все три таблицы загружены в проект:

Осталась лишь одна небольшая проблемка. Нужно прописать внутри проекта, как обращаться к этой базе. У меня до сих пор там были прописаны данные для доступа к локальной базе на моём компьютере. В облаке база совсем другая, с другим паролем и с другим адресом.
В проекте мой HibernateUtil.java класс использует xml-файл для конфигурации, поэтому менять буду его:
public class HibernateUtil {
private static SessionFactory sessionFactory = buildSessionFactory();
public HibernateUtil() {
}
private static SessionFactory buildSessionFactory() {
try {
return (new Configuration()).configure("sqlserverMain.cfg.xml").buildSessionFactory();
} catch (Exception var1) {
throw new ExceptionInInitializerError(var1);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
Итак, в sqlserverMain.cfg.xml я меняю параметры hibernate.connection.username на root (или что там у вас в Variables — MYSQLUSER), hibernate.connection.password меняю на пароль от базы (MYSQLPASSWORD).
И осталось изменить hibernate.connection.url. Для подключения railway советуют создать новую переменную и присвоить ей значение ${{ MySQL.MYSQL_URL }}. Потом эту переменную можно использовать в настройках.
Но можно также «вшить» адрес в наш файл настроек:
jdbc:mysql://interchange.proxy.rlwy.net:10144/railway?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
Указываем jdbc:mysql://, потом хост, через двоеточие номер порта, через слэш название базы. Пушим эти изменения на гит, и готово!
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="hibernate.connection.url">
jdbc:mysql://mysql.railway.internal:3306/railway?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">****************</property>
<!-- Диалект и пул соединений -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</property>
<property name="hibernate.connection.pool_size">50</property>
<property name="hibernate.show_sql">true</property>
<!-- Маппинги -->
<mapping class="com.chart.TopChart.data.model.Song" />
<mapping class="com.chart.TopChart.data.model.Chart" />
<mapping class="com.chart.TopChart.data.model.Position" />
</session-factory>
</hibernate-configuration>
Теперь у нас есть:
- Приложение, загруженное через github, которое будет обновляться автоматически после каждого нового пуша.
- База данных, которая копирует структуру локальной базы данных и содержит оттуда все данные (мы залили дамп)
- Доступ к базе данных внутри этого облачного проекта (мы поменяли данные для доступа к локальной базе на данные для доступа этой облачной базы, включая юзера, пароль и адрес)
Приложение открывается и, пока не истечёт мой бесплатный план, будет оставаться там.

1 Comment