Running MySQL on Kamal

MySQL accessory

MySQL can be added as any other accessory to the Kamal's configuration file. We'll just specify a MySQL Docker image, the command to run, and the servers to run MySQL on:

# config/deploy.yml
...
mysql:
  image: mysql:8.3
  # host: 1.1.1.3
  # port: 3306
  roles:
    - web
  env:
    clear:
      MYSQL_ROOT_HOST: '%'
    secret:
      - MYSQL_ROOT_PASSWORD
  files:
    - config/init.sql:/docker-entrypoint-initdb.d/setup.sql
  directories:
    - data:/var/lib/mysql

If we want to run an independent MySQL server, we can provide a host IP address, otherwise we can tell Kamal which roles depend on it. Since MySQL is a database we should mount a volume for data persistance across restarts. Here we are mounting a local data to the container's /var/lib/mysql directory.

Providing ENVs

The MySQL image requires some environment variables to be set, namely MYSQL_ROOT_HOST and MYSQL_ROOT_PASSWORD:

# config/deploy.yml
...
mysql:
  ...
  env:
    clear:
      # MYSQL_USER:
      # MYSQL_PASSWORD:
      # MYSQL_DATABASE:
      MYSQL_ROOT_HOST: '%'
    secret:
      - MYSQL_ROOT_PASSWORD
  ...

The official Docker image will use these variables to create the database for you and you'll be able to connect to it with the following URLs:

"mysql2://root:MYSQL_ROOT_HOST@DB_HOST/MYSQL_DATABASE"

# If you provided a specific user and password for the superuser
"mysql2://MYSQL_USER:MYSQL_PASSWORD@DB_HOST/MYSQL_DATABASE"

Your DB_HOST will either be the IP address or the internal service name on the local Docker private network.

If you have created a private network called private, then add a network option:

service: myservice
...
mysql:
  ...
  options:
    network: "private"

Once added your DB_HOST will be myservice-mysql.

Initializing the database

Since the database cluster will be empty, we can initialize the database with a custom SQL file.

# config/deploy.yml
...
mysql:
  iimage: mysql:8.3
  ...
  files:
    - config/init.sql:/docker-entrypoint-initdb.d/setup.sql
  directories:
    - data:/var/lib/mysql

Here the local config/init.sql will be used as a setup script. It can look like:

# config/init.sql
CREATE DATABASE myservice_production;

Deploying MySQL

Once the configration is complete, we can instruct Kamal to boot MySQL on the specified servers:

$ kamal accessory boot mysql