authored Jul 3 2015 by kengz
- Account with Google Cloud Platform.
- Install Google Cloud Platform SDK to use
cloud
in the terminal. - Install Docker for the VM container.
- Locally, login for the first time:
gcloud auth login
- Create and enable billing for a project in Google Developers Console. Name the project and remember the Project ID for use in
gcloud
. Say it is appid-123. - Have your NodeJS app, say in the folder coolapp, with entry point
app.js
.
We will deploy by building a custom runtime using Google Compute Engine, borrowing presets from Google App Engine.
Go into your project root directory, and add these files:
Dockerfile
for the VM to use nodejs runtime
# [START docker]
FROM google/nodejs-runtime
# [END docker]
app.yaml
to configure the GCE VM. Details here, also more examples (in Python, but relevant).
Below, runtime: custom
and vm: true
are required to run GCE VM with Custom Runtimes. See further below on behind the scene.
# [START runtime]
runtime: custom
vm: true
api_version: 1
module: default
# [END runtime]
# [START resources]
resources:
cpu: .5
memory_gb: 1.3
disk_size_gb: 10
# [END resources]
# [START scaling]
automatic_scaling:
min_num_instances: 1
max_num_instances: 3
cool_down_period_sec: 60
cpu_utilization:
target_utilization: 0.5
# [END scaling]
env_variables:
NODE_ENV: production
.dockerignore
to list files to keep away from deployment.
node_modules
*.log
Every time when you do things with gcloud, you have to:
- set the current project in gcloud
gcloud config list
gcloud config set project appid-123
- Initialize and set the VM environment for Docker
boot2docker up
eval "$(boot2docker shellinit)"
gcloud preview app deploy app.yaml --set-default
This will take minutes if it's the first deployment of the project. Consecutive deployments should be faster because it seems that they build off the existing one by checking only the differences. Note that each deployment creates a new VM instance, and no you cannot modify a VM instance. Just redeploy and delete the old ones (see below).
The --set-default
tag sets this to the IS_DEFAULT version of the module, so it will be the one running out of many deployed VMs.
Known bug: sometimes it just hangs at Building and pushing image for module [default]
for a really long time. You can cancel it, and any following deployments will experience the same issue. To solve it, just restart your computer. The exact cause is not known, but restarting seems to reset some configs in gcloud/Docker that cause the issue.
See behind the scene below.
You can monitor all your VM instances on GCE by
gcloud compute instances list
With the tweaks above you need to do some things differently. Say you update your app and want to deploy the latest version. You have to rerun the command above to deploy a new VM instance; you can't access and reconfigure an existing one easily. Yet, as noted above, deploying a new one is good enough since it's fast and it builds off the previous by checking only differences.
To delete a VM instance you cannot do it normally from the terminal. Just do it from the Google Developer Console: select your project, under Compute > Compute Engine, select the instances to delete.
You may also need to go under App Engine > Instances / Versions to delete.
The VM manual page says:
Incoming HTTP requests for your application will be routed to port 8080. It is the responsibility of the container to interpret these requests and route them appropriately.
You'll need to enable the port and set the correct default version for your app to work. Do this from the Google Developer Console.
Your app might be called on a different port, say 1234. First, go to Compute Engine > Networks > default to add a firewall rule for your port (the target tag must be blank). Now the port is opened, and all calls to it will be forwarded to 8080.
Next, make sure your deployed version IS_DEFAULT (it should be with the --set-default tag when deploying). Go to App Engine > Versions and select a proper deployed version (number from when you deployed from the terminal) to be the default.
Alternatively, do it from the terminal by looking up the version for the module first,
gcloud preview app modules list
which returns something like
MODULE VERSION IS_DEFAULT
default 20150704t180104 *
default 20150704t183125 -
Set the new IS_DEFAULT version and delete the old:
gcloud preview app modules set-default default --version 20150704t183125
gcloud preview app modules delete default --version 20150704t180104
Google Cloud Platform houses over 10 products, which are all integrated. The products relevant to us now are Google Compute Engine (GCE) and Google App Engine (GAE). Google also hosts Git now, called Cloud Source Repositories (CSR), and is a direct competitor of Github.
GAE and CSR can be integrated; you push to CSR, your code gets built, tested, and deployed onto GAE and voila, you have your app running automatically. This is very much like pushing to Github and auto-deploy to Heroku. However for now, GAE supports only Python, Java, PHP, Go; so the magic above won't work for anything else.
Other languages will have to use GCE, which is basically raw VMs for you to play with. You can create a VM instance, SSH into it, and install Node etc. manually. However Google introduced Custom Runtimes which saves you from doing these.
With Custom Runtimes, you specify the extra files to, well, host a custom runtime. So, when you deploy, GCE allocates a VM instance for you (with Debian/Linux installed), and Docker pulls some stuff from GAE and from google/nodejs-runtime to create a Container within the VM, so it will run Node. Voila, your app is now deployed, just as magical.
Basically, you get a mix of GCE calling GAE with Docker, and it gets done.
Save these aliases into your .bash_profile
for an easier life.
### gcloud
# set env for boot2docker each time
alias boot2eval='boot2docker up; eval "$(boot2docker shellinit)"'
# list all the projects
alias glist='gcloud config list'
# set project to a valid one. e.g. gset appid-123
alias gset='gcloud config set project'
# deploy your app module and set as IS_DEFAULT. e.g. gdeploy app.yaml
_deploy() {
gcloud preview app deploy $1 --set-default
}
alias gdeploy=_deploy
# see the VM instances of your project
alias ginstances='gcloud compute instances list'
# list modules
alias glistmod='gcloud preview app modules list'
# set the new IS_DEFAULT version of a module
alias gsetdefault='gcloud preview app modules set-default default --version'
# set the new IS_DEFAULT version of a module
alias grmdefault='gcloud preview app modules delete default --version'
More reference on Command-Line Tool Guide (gcloud).