This post details how to automate the deployment of a Docker application to Google App Engine using Travis CI.
In the previous post, we wrote a tiny service called hellogo
with a structure like so:
.
├── Dockerfile
├── app.yaml
└── main.go
The app.yaml
file instructs Google App Engine to use the Dockerfile
to run the application.
Be sure to have your service already running in Google App Engine before continuing!
Grant Travis Access to GAE
First need to create a Service Account, which according to GAE's docs is:
...an account that can be used by applications to access Google services programmatically.
Navigate to the Service Accounts page by typing "Service Accounts" in the search bar:
Click the "Create Service Account" link and fill out the form.
- Name the Service account "Travis Deploy"
- Select the Role
Project -> Editor
in the dropdown - Check "Furnish a new private key"
The result should be a page like so:
Click the Create button, and we'll receive a file named a bit like ~/Downloads/hellogo-a142e365006e.json
:
{
"type": "service_account",
"project_id": "hellogo-147000",
"private_key_id": "a142e365006e88d8c1dd66effc0d55e84400131f",
"private_key": "-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----\n",
"client_email": "travis-deploy@hellogo-147000.iam.gserviceaccount.com",
"client_id": "102324744274179729731",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/travis-deploy%40hellogo-147000.iam.gserviceaccount.com"
}
Note Travis requires the Editor
role to access all the APIs needed to deploy our Docker service.
This role is extremely permissive - consider running the service in an isolated project
Ideally we'd be able to select only specific permissions, but currently using Editor
is the only way.
Finally, type "App Engine Admin API" in the search bar and click Enable:
This API is required for Travis to make requests on behalf of the Service Account.
Create the .travis.yml
Now that Travis has access to GAE, we're ready to write our .travis.yml
:
sudo: required
services:
- docker
language: go
deploy:
provider: gae
project: hellogo-147000
keyfile: gce.json
verbosity: debug
on: master
Notice that we've enabled Travis' Docker support by choosing sudo: required
and services: - docker
- this is required for Travis to build the container and upload it to Google App Engine's Container Registry.
The next line, language: go
is required as you must choose at least one language, even if it's not being used.
Finally, we have a deploy
target which contains the following lines:
provider: gae
- use the Google App Engine deploy targetproject: hellogo-147000
- our Project IDkeyfile: gce.json
- the deploy key to useverbosity: debug
- log-levelon: master
- only deploy for commits on master
Be sure to use the Project ID, hellogo-147000
in this case, which will likely have some integer appended to it to ensure uniqueness. Type "projects" into the search bar to pull up the IAM & Admin page to locate the Project ID:
Encrypt our deploy key
Start by moving the deploy key to our project and make sure that it won't be committed:
$ mv ~/Downloads/hellogo-a142e365006e.json gce.json
$ echo "gce.json" >> .gitignore
Now navigate to travis-ci.org/profile and enable builds for the project by clicking the switch next to the repo:
Install the Travis cli and login:
$ ruby -v
ruby 2.0.0p648 (2015-12-16 revision 53162) [universal.x86_64-darwin15]
$ sudo gem install travis -v 1.8.2 --no-rdoc --no-ri
$ travis version
1.8.2
$ travis login
Encrypt gce.json
by running travis encrypt-file
:
$ travis encrypt-file gce.json --add
Detected repository as breerly/hellogo, is this correct? |yes|
encrypting gce.json for breerly/hellogo
storing result as gce.json.enc
storing secure env variables for decryption
This creates a new file called gce.json.enc
and modifies our .travis.yml
to add the following section:
before_install:
- openssl aes-256-cbc -K $encrypted_7748a1005700_key -iv $encrypted_7748a1005700_iv
-in gce.json.enc -out gce.json -d
As you might have guessed, the call to openssl
is responsible for decrypting our gce.json.enc
into gce.json
on Travis' end.
Commit the gce.json.enc
and the changes to .travis.yml
to your repo, leaving the following committed files:
.
├── .gitignore
├── .travis.yml
├── Dockerfile
├── gce.json.enc
└── main.go
Note that gce.json
should not be committed!
Push and test
To test our application, let's change the message of our program in main.go
:
fmt.Fprintln(w, "Hello Go! Brought to you by Travis CI.")
Now commit and push; in ~5 minutes the build should have passed:
Check out the production site, and viola:
Cheers.