Matthew
Matthew

Reputation: 11

Laravel migration for AppEngine in CloudBuild

We have a Laravel project running in app engine. We deploy everythough through CloudBuild which works great. Previously we did database migration manuallly but now I want to include to CloudBuild.

In CloudBuild I could not find any php package to be able to do db migation.

Current cloudbuild.yaml is the followgin:

steps:
#Install
- name: 'gcr.io/cloud-builders/npm'
  args: ['install']

#Build
- name: 'gcr.io/cloud-builders/npm'
  args: ['run', 'prod']

#Deploy Test
- name: 'gcr.io/cloud-builders/gcloud'
  args: ['app', 'deploy', 'app.yaml']

Any tip how to do php artisan migrate after deploying codebase?

Upvotes: 1

Views: 1270

Answers (3)

Vinny
Vinny

Reputation: 41

Google recommends that you do not run database schema updates in the app's startup code and instead run database schema updates on a separate cloud build step when deploying. See this YouTube video clip made by Google's official channel.

Run the database migrations by using the app-engine-exec-wrapper which is a "helper" for the Cloud SQL Auth Proxy. See the official documentation for more information and a example: https://cloud.google.com/python/django/run#cloudbuild-automation

I was successfully able to run php artisan migrate --force while deploying a Laravel app to a Cloud Run service by adding a extra 4th migration step mentioned above to the cloudbuild.yaml file. I was stuck on this for a while but found the above answers help point me in the right direction. I also found this post to be a helpful example and may be more useful if you are using NPM: Run node.js database migrations on Google Cloud SQL during Google Cloud Build

Here is my entire cloudbuild.yaml file:

steps:
  - name: gcr.io/cloud-builders/docker
    args:
      - build
      - '--no-cache'
      - '-t'
      - '$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA'
      - .
      - '-f'
      - Dockerfile
    id: Build
  - name: gcr.io/cloud-builders/docker
    args:
      - push
      - '$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA'
    id: Push
  - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk:slim'
    args:
      - run
      - services
      - update
      - $_SERVICE_NAME
      - '--platform=managed'
      - '--image=$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA'
      - >-
        --labels=managed-by=gcp-cloud-build-deploy-cloud-run,commit-sha=$COMMIT_SHA,gcb-build-id=$BUILD_ID,gcb-trigger-id=$_TRIGGER_ID,$_LABELS
      - '--region=$_DEPLOY_REGION'
      - '--quiet'
    id: Deploy
    entrypoint: gcloud
  - name: gcr.io/google-appengine/exec-wrapper
    args:
      - '-i'
      - '$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA'
      - '-e'
      - DB_CONNECTION=mysql
      - '-e'
      - 'DB_SOCKET=/cloudsql/$_DB_CONNECTION'
      - '-e'
      - DB_PORT=3306
      - '-e'
      - DB_DATABASE=$_DB_DATABASE
      - '-e'
      - DB_USERNAME=$_DB_USERNAME
      - '-e'
      - DB_PASSWORD=$_DB_PASSWORD
      - '-s'
      - '$_DB_CONNECTION'
      - '--'
      - php
      - /app/artisan
      - migrate
      - '--force'
    id: Migrate
    waitFor:
      - Build
      - Push
      - Deploy
timeout: 1200s
images:
  - '$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA'
options:
  substitutionOption: ALLOW_LOOSE
tags:
  - gcp-cloud-build-deploy-cloud-run
  - gcp-cloud-build-deploy-cloud-run-managed
  - prod_deployment

Upvotes: 3

Ahmed Ghorab
Ahmed Ghorab

Reputation: 31

just wanted to share my way of doing the migration

I'm using Cloud run to host the app and Cloud SQL for the database.

also using 'gcr.io/google-appengine/exec-wrapper' to wrap the cloud_sql_proxy.

it's a 4 step build

  1. to build the container from dockerFile
  2. push the build docker to Container Registry
  3. automatic deploy to Cloud Run
  4. Fetch the new Container from Container Registry and Run Php artisan migrate also passing the Database username and password from secret Manager.
steps:
  # Build the container image
  - name: 'gcr.io/cloud-builders/docker'
    args: ['build', '-t', 'gcr.io/$PROJECT_ID/<SERVICE-NAME>:$COMMIT_SHA', '-f', '.Dockerfile', '.']
  # Push the container image to Container Registry
  - name: 'gcr.io/cloud-builders/docker'
    args: ['push', 'gcr.io/$PROJECT_ID/<SERVICE-NAME>:$COMMIT_SHA']
  # Deploy container image to Cloud Run
  - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
    entrypoint: gcloud
    args:
      - 'run'
      - 'deploy'
      - '<SERVICE-NAME>'
      - '--image'
      - 'gcr.io/$PROJECT_ID/<SERVICE-NAME>:$COMMIT_SHA'
      - '--region'
      - '<REGION>'

  - name: 'gcr.io/google-appengine/exec-wrapper'
    entrypoint: 'bash'
    args:
      - -c
      - |
        /buildstep/execute.sh \
        -i gcr.io/$PROJECT_ID/<SERVICE-NAME>:$COMMIT_SHA \
        -e DB_CONNECTION=mysql \
        -e DB_SOCKET=/cloudsql/<DB-CONNETION> \
        -e CLOUD_SQL_CONNECTION_NAME=<DB-CONNETION> \
        -e DB_DATABASE=<DATABASE_NAME> \
        -e DB_USERNAME=$$USERNAME \
        -e DB_PASSWORD=$$PASSWORD \
        -s <DB-CONNETION> \
        -- php artisan migrate --force
    secretEnv: ['USERNAME', 'PASSWORD']

images:
  - 'gcr.io/$PROJECT_ID/<SERVICE-NAME>:$COMMIT_SHA'

availableSecrets:
  secretManager:
    - versionName: projects/<PROJECT_ID>/secrets/<SECRET_ID>/versions/latest
      env: 'PASSWORD'
    - versionName: projects/<PROJECT_ID>/secrets/<SECRET_ID>/versions/latest
      env: 'USERNAME'

Upvotes: 2

Stefan Neacsu
Stefan Neacsu

Reputation: 693

You can try using Cloud SQL Proxy and Docker Compose in order to achieve the migration.

First of all you will need to setup docker-compose for Cloud Build and then create a service account.

Your docker-compose file should look something like this:

version: '3.7'

services: 
  app:
    build:
      context: .
      dockerfile: Dockerfile
    restart: "no"
    links:
      - database
    tty: true
    volumes: 
      - app:/var/www/html
    env_file: 
      - ./.env
    depends_on: 
      - database
      

  database:
    image: gcr.io/cloudsql-docker/gce-proxy
    restart: on-failure
    command: 
      - "/cloud_sql_proxy" 
      - "-instances=<INSTANCE_CONNECTION_NAME>=tcp:0.0.0.0:3306" 
      - "-credential_file=/config/sql_proxy.json"
    volumes: 
      - ./sql_proxy.json:/config/sql_proxy.json:ro

volumes: 
  app:

And your cloudbuild.yaml file should look something like this:

- name: 'gcr.io/$PROJECT_ID/docker-compose'
  id: Compose-build-cloudProxy
  args: ['build']

- name: 'gcr.io/$PROJECT_ID/docker-compose'
  id: Compose-up-cloudProxy
  args: ['up', '--timeout', '1', '--no-build', '-d']

- name: 'bash'
  id: Warm-up-cloudProxy
  args: ['sleep', '5s']

- name: 'gcr.io/cloud-builders/docker'
  id: Artisan-Migrate
  args: ['exec', '-i', 'workspace_app_1', 'php', 'artisan', 'migrate']

- name: 'gcr.io/$PROJECT_ID/docker-compose'
  id: Compose-down-cloudProxy
  args: ['down', '-v']

Also you could check the following link which has some hefty php tools that would might help with the process like the php artisan migrate.

Upvotes: 0

Related Questions