Prisma in Azure container instances: can't reach database server

121 Views Asked by At

I have a container group which consists of database(MySQL), client app(SSR, SvelteKit with node-adapter) and reverse proxy(Caddy, for enabling automatic HTTPS)

Dockerfile for database:

FROM mysql:8.2.0
COPY init-prod.sql /docker-entrypoint-initdb.d/init.sql
EXPOSE 3306

init-prod.sql mentioned in the database Dockerfile:

GRANT ALL PRIVILEGES ON <database_name>.* TO '<database_user>'@'%';
-- Required for Prisma Migrate
GRANT CREATE, ALTER, DROP, REFERENCES ON *.* TO '<database_user>'@'%';
-- Flush privileges to apply changes
FLUSH PRIVILEGES;

Dockerfile for SvelteKit application. The container from which I'm trying to execute npx prisma migrate deploy is created from this image.

FROM node:18.19.0 as build
WORKDIR /app
COPY . .
RUN npm ci --omit dev
RUN npm run build

FROM node:18.19.0
COPY --from=build /app/package.json .
COPY --from=build /app/.env.production .env
COPY --from=build /app/node_modules node_modules
COPY --from=build /app/prisma prisma
COPY --from=build /app/build .
CMD ["npm", "run", "prod"]

After successful deployment to Container Instances I'm trying to run migrations with following Azure CLI command:

az container exec --resource-group <resource_group> --name <container_group> --container-name app --exec-command "npx --yes prisma migrate deploy"

The command output:

Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": MySQL database "txtsummprod" at "db:3306"

Error: P1001: Can't reach database server at `db`:`3306`

Please make sure your database server is running at `db`:`3306`.

Prisma DATABASE_URL env variable is formed like this:

mysql://<database_user>:<database_password>@db:3306/<database_name>?connect_timeout=300

I've tried:

  1. adding ?connect_timeout=300 to DATABASE_URL per this answer
  2. changing node image versions per this answer

But still, no luck. Locally migrations are applied just fine, the problem appears only when I'm attempting to execute npx prisma migrate deploy in a container deployed to Container Instances

According to db container logs from Azure Container Instances everything seem to be ok and database is ready to accept connections:

2024-01-03 22:34:00+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.2.0-1.el8 started.
2024-01-03 22:34:01+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2024-01-03 22:34:01+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.2.0-1.el8 started.
ln: failed to create symbolic link '/var/lib/mysql/mysql.sock': Operation not supported
2024-01-03T22:34:03.057381Z 0 [System] [MY-015015] [Server] MySQL Server - start.
2024-01-03T22:34:03.348494Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead.
2024-01-03T22:34:03.377157Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.2.0) starting as process 150
2024-01-03T22:34:03.526733Z 0 [Warning] [MY-000054] [Server] World-writable config file '/var/lib/mysql/auto.cnf' is ignored.
2024-01-03T22:34:03.537967Z 0 [Warning] [MY-010107] [Server] World-writable config file '/var/lib/mysql/auto.cnf' has been removed.
2024-01-03T22:34:03.543031Z 0 [Warning] [MY-010075] [Server] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: 328cd822-aa88-11ee-8f84-00155d592a61.
2024-01-03T22:34:03.623222Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2024-01-03T22:34:10.269749Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2024-01-03T22:34:11.972853Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
2024-01-03T22:34:11.977611Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
2024-01-03T22:34:12.071977Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
2024-01-03T22:34:12.168356Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock
2024-01-03T22:34:12.168448Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.2.0'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server - GPL.

YAML for deployment to Azure Container Instances looks like this:

apiVersion: 2021-10-01
location: eastus
name: txt-summ
properties:
  containers:
    - name: reverse-proxy
      properties:
        image: summacr.azurecr.io/reverse-proxy:latest
        ports:
          - port: 80
            protocol: TCP
          - port: 443
            protocol: TCP
        resources:
          requests:
            memoryInGB: 1.0
            cpu: 1.0
          limits:
            memoryInGB: 1.0
            cpu: 1.0
        volumeMounts:
          - name: proxy-data
            mountPath: /data
          - name: proxy-config
            mountPath: /config
    - name: app
      properties:
        image: summacr.azurecr.io/app:latest
        resources:
          requests:
            cpu: 1.5
            memoryInGB: 1.5
        ports:
          - port: 3000
            protocol: TCP
    - name: db
      properties:
        image: summacr.azurecr.io/db:latest
        resources:
          requests:
            cpu: 1.0
            memoryInGB: 1.0
        volumeMounts:
          - name: db-data
            mountPath: /var/lib/mysql
        environmentVariables:
          - name: MYSQL_USER
            value: $DB_USER
          - name: MYSQL_PASSWORD
            value: $DB_PASSWORD
          - name: MYSQL_ROOT_PASSWORD
            value: $DB_ROOT_PASSWORD
          - name: MYSQL_DATABASE
            value: $DB_NAME
        ports:
          - port: 3306
            protocol: TCP
  ipAddress:
    dnsNameLabel: txt-summ
    ports:
      - port: 80
        protocol: TCP
      - port: 443
        protocol: TCP
    type: Public
  imageRegistryCredentials:
    - server: $ACR_LOGIN_SERVER
      username: $ACR_USERNAME
      password: $ACR_PASSWORD
  volumes:
    - name: proxy-data
      azureFile:
        shareName: $PROXY_DATA_FILE_SHARE_NAME
        storageAccountName: $STORAGE_ACCOUNT_NAME
        storageAccountKey: $STORAGE_ACCOUNT_KEY
    - name: proxy-config
      azureFile:
        shareName: $PROXY_CONFIG_FILE_SHARE_NAME
        storageAccountName: $STORAGE_ACCOUNT_NAME
        storageAccountKey: $STORAGE_ACCOUNT_KEY
    - name: db-data
      azureFile:
        shareName: $DB_DATA_FILE_SHARE_NAME
        storageAccountName: $STORAGE_ACCOUNT_NAME
        storageAccountKey: $STORAGE_ACCOUNT_KEY
  osType: Linux
type: Microsoft.ContainerInstance/containerGroups
1

There are 1 best solutions below

1
Max Liapkalo On

So it looks like it wasn't a timing issue but database url issue. While database url

mysql://<user>:<password>@db:3306/<database>

works fine locally(given that your database service in docker compose named as db) it won't let you to establish database connection in ACI.

Changing DATABASE_URL env variable in ACI to

mysql://<user>:<password>@localhost:3306/<database>

did the trick.