1

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?

Matthew
  • 11
  • 1

3 Answers3

2

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'
Ahmed Ghorab
  • 31
  • 1
  • 4
2

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

Vinny
  • 31
  • 7
0

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.

Stefan Neacsu
  • 653
  • 3
  • 12
  • That would theoratically do, but in this case I have to pull the git repo with the laravel to be able to do the migration, right? – Matthew Sep 10 '20 at 15:09
  • You mean the php tools one? Not necessarily that is more like an alternative that could work since it has some tools that could help in the process. – Stefan Neacsu Sep 14 '20 at 08:34
  • $PROJECT_ID has been replaced to current project_id I get the following error during deploy: Pulling image: gcr.io/$PROJECT_ID/docker-compose Using default tag: latest Error response from daemon: manifest for gcr.io/$PROJECT_ID/docker-compose:latest not found: manifest unknown: Failed to fetch "latest" from request "/v2/$PROJECT_ID/docker-compose/manifests/latest". – Matthew Sep 18 '20 at 09:02
  • This usually appears when you are not choosing the correct tag that you want to pull. – Stefan Neacsu Sep 21 '20 at 11:12
  • There is no docker-compose package. This is the problem. – Matthew Sep 22 '20 at 12:17
  • You can try adding the package in the Dockerfile. – Stefan Neacsu Sep 28 '20 at 12:18