Deploy Node.js and connect MySQL by fly.io
Table of contents
- Step for deploying the application (app)
- Install CLI
- Sign up and Sign in
- Launch the app to fly.io
- Set the sensitive environmental variable
- Deploy the app in fly.io
- Connect the database to your app (MySQL)
- Create an independent folder and launch it.
- Set some parameters and secrets
- Deploy the database and connect it by app
- Connect the database app from outside(MySQL GUI)
When Heroku canceled its free policy last November, developers are looking for other small free deployment platforms to deploy their side projects. Currently, Vercel, Render, and fly.io are used to do this. The reason for choosing fly.io this time is that I had read and attempted to deploy on it before, but failed. Now I have time to study the method of deployment in this platform.
Step for deploying the application (app)
Install CLI
Open your terminal and run the code below to install flyctl
.
Homebrew:
$ brew install flyctl
Script:
$ curl -L https://fly.io/install.sh | sh
Notice: The executed command
fly xxxx
can be written inflyctl xxxx
Sign up and Sign in
Sign up for the account and need to add the credit card number cause this platform will not allow you to pass the authentication when you deploy. After creating the account, run the code line below in your terminal.
$ fly auth login
and it will open the browser to log in to your account. After login successfully, it will show the figure below.
Launch the app to fly.io
Open the path of your app in the terminal and run the code as follows:
$ fly launch
and it shows some messages that you need to decide:
- Choose an app name (leave blank to generate one)
- Choose a region for deployment
- Would you like to set up a Postgresql database now?
- Would you like to set up an Upstash Redis database now?
- Would you like to deploy now?
The app name only accepts lowercase letters, dashes, and numbers or you can leave it blank and it will generate itself. In the last message, I suggest that you don't need to deploy your app immediately because your project folder also creates a new file (fly.toml) at the same time. The deployment configuration is in the toml file. You can read the official document to know what each parameter does in this file (app configuration in toml). Here is an example toml file:
# fly.toml app configuration file generated for app_name on 2023-05-08T12:10:20+08:00
#
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
#
app = "your_app_name"
kill_signal = "SIGINT"
kill_timeout = 5
# Deploy region
primary_region = "sin"
processes = []
[env]
PORT = "8080"
NODE_ENV = "production"
[deploy]
release_command = "npx sequelize db:migrate"
[experimental]
auto_rollback = true
[[services]]
http_checks = []
internal_port = 8080
processes = ["app"]
protocol = "tcp"
script_checks = []
[services.concurrency]
hard_limit = 25
soft_limit = 20
type = "connections"
[[services.ports]]
force_https = true
handlers = ["http"]
port = 80
[[services.ports]]
handlers = ["tls", "http"]
port = 443
[[services.tcp_checks]]
grace_period = "1s"
interval = "15s"
restart_limit = 0
timeout = "2s"
There is one thing you need to notice the connected PORT. The default value is 8080 and if you don’t change this, you have to set the same port value in your app.js.
Set the sensitive environmental variable
In toml file, it has a risk of security to write the secrete in [env]. You can run the code below in the terminal to set the secrets and fry.io encrypt these data.
# Set the secret
flyctl secrets set FACEBOOK_SECRET=xxxxxxx
# Remove the secret
flyctl secrets unset FACEBOOK_SECRET=xxxxxxx
# show the list of secrets
flyctl secrets list
Deploy the app in fly.io
After checking the configuration, you can start to deploy by running the code:
$ fly deploy
You will see the figure if it deployed successfully.
You can go to the website fly.io to check the dashboard
or run the code to check it in terminal. It showed the example below.
# Choose one to run in terminal
fly status
fly status -a app_name
# The result in terminal
App
Name = xxxxx
Owner = personal
Hostname = xxxx.fly.dev
Image = xxxx:deployment-xxxxx
Platform = machines
Machines
ID PROCESS VERSION REGION STATE HEALTH CHECKS LAST UPDATED
xxxxxxxxxxxxxx app 2 nrt started 2023-05-08T02:46:04Z
After deploying, you can run the code fly open
to check the website of app.
Connect the database to your app (MySQL)
From the description of the document, the step to deploy the database as an app on fly.io. Some settings are a little different. Here are the steps:
Create an independent folder and launch it.
The folder you can place it anywhere and run the code below:
# You can name the folder by yourself
mkdir flyio-mysql
cd flyio-mysql
Then you have to run fly launch
to launch the database to create the fly.toml. Of cause, you have to set the location of database.
Set some parameters and secrets
(a) Set the volume of database:
Run the code to set the volume of your database and the unit is GB. You can set only 1 GB is your database is just for side projects.
# Create a volume named "mysqldata" within our app "wen-mysql"
fly volumes create mysqldata --size 1 # gb
There is one thing you have to notice that this database can be shared by many apps. If you want to expense scale, you have to change the setting by following the document.
(b) Set the secrets:
Run the code as follows to set password of database
# Set secrets:
# MYSQL_PASSWORD - password set for user $MYSQL_USER
# MYSQL_ROOT_PASSWORD - password set for user "root"
fly secrets set MYSQL_PASSWORD=xxxxx MYSQL_ROOT_PASSWORD=xxxxx
(c) Set the fly.toml file in database app
Open your fry.toml and notice that your app is on V2 of fly platform. Here is the setting on V2 in official document. (It is a different setting if your app is on V1, please watch the official document.)
# fly.toml app configuration file generated for wen-mysql on 2023-05-08T22:00:35+08:00
#
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
#
app = "your_app_name"
kill_signal = "SIGINT"
kill_timeout = 5
# If copy/paste'ing, adjust this
# to the region you're deploying to
primary_region = "sin"
[processes]
app = "--datadir /data/mysql --default-authentication-plugin mysql_native_password --performance-schema=OFF --innodb-buffer-pool-size 64M"
[mounts]
source="mysqldata"
destination="/data"
# MYSQL_DATABASE can name your database and will created aftering deploy
[env]
MYSQL_DATABASE = "some_db"
MYSQL_USER = "non_root_user"
# As of 04/25/2023:
# MySQL 8.0.33 has a bug in it
# so avoid that specific version
[build]
image = "mysql:8.0.31"
In the parameter of [env]
, you can write the name of database and it will be created at the same time when the app is deployed. If you want to create the other database, you have to connect this app from outside to use the command in terminal or GUI tool.
Deploy the database and connect it by app
Run the code fly deploy
to deploy the database app and it shows the figure when deploying successfully.
Then, open your app to which you want to connect to the database app and change the settings inside config.js and fly.toml.
At the section of production in config.js file, you need to adjust the name of database and host. The host is your name of database app with “.internal” appended. Here is an example of setting.
{
"development": {
...
},
"test": {
...
},
"production": {
"username": "root",
"password": "xxxx",
"database": "your_database_name",
"host": "database_app_name.internal",
"dialect": "mysql"
}
}
In a MySQL database, you need to run migration or set a seeder in your app. Go to the fly.toml file in your app and check if it has a [deploy]
section. Then, add the release_command and input the command that you want to run, such as npx sequelize db:migrate
or nps sequelize db:seed
. Finally, deploy the app. This command will be executed during deployment.
# fly.toml app configuration file generated for todo-sequelize on 2023-05-08T12:10:20+08:00
#
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
#
app = "todo-sequelize"
kill_signal = "SIGINT"
kill_timeout = 5
primary_region = "sin"
processes = []
[env]
PORT = "8080"
NODE_ENV = "production"
# only build one command when deploying
# need to redeploying if you want to build the other command
[deploy]
release_command = "npx sequelize db:migrate"
[experimental]
auto_rollback = true
[[services]]
http_checks = []
internal_port = 8080
processes = ["app"]
protocol = "tcp"
script_checks = []
[services.concurrency]
hard_limit = 25
soft_limit = 20
type = "connections"
[[services.ports]]
force_https = true
handlers = ["http"]
port = 80
[[services.ports]]
handlers = ["tls", "http"]
port = 443
[[services.tcp_checks]]
grace_period = "1s"
interval = "15s"
restart_limit = 0
timeout = "2s"
If you run the command successfully during deploying, it will show the image below.
However, there is only one command can be declared. If you want to run another command, you have to re-write the release_command
and deploy it again.
Connect the database app from outside(MySQL GUI)
In fly app platform, it is different from Heroku to connect database of MySQL. It sets the proxy as localhost to activate the database without URL. The default value of proxy is 3306 and you can run the code as follows:
# Default port is 3306 and you can run this code if it is not used
fly proxy 3306 -a wen-mysql
# if port 3306 is used you can use this code to change the default port.
fly proxy 13306:3306 -a wen-mysql
Most people set proxy 3306 to their MySQL. You can run the second code to do the same thing. and it will show the success as the following image.
Don’t turn off it and open your GUI tool to set the configuration as follows:
Now you can operate the database in GUI.
There is one thing you need to notice: the hostname is provided on the fly.io dashboard. However, if you want to operate the remote database on your computer, you must execute fly commands through the CLI and activate your local IP address, 127.0.0.1. Therefore, the hostname should be set to your local IP, not a URL.
Reference