- Currently running locally and auth'ing with
gcloud auth
:
❯ gc auth list
Credentialed Accounts
ACTIVE ACCOUNT
* [email protected]
To set the active account, run:
$ gcloud config set account `ACCOUNT`
This is a GitHub Action that can deploy any Docker-based app to a Google Cloud VM using Docker and Docker Compose.
The Action will:
- Create a new VM in your Google Cloud account.
- Copy this repo to the VM.
- Launch this repo's application using
docker compose up
. - Expose the application to the Internet and provide the publicly accessible URL as an output in the GitHub GUI.
Obviously this refers to GCP but the flow is the same!
- Files for Docker
- A Google Cloud account
Your app needs a Dockerfile
and a docker-compose.yaml
file.
For more details on setting up Docker and Docker Compose, check out Bitovi's Academy Course: Learn Docker
2. A Google Cloud account
You'll need to enable authentication from a Google Cloud account.
repo_env
- A file in your repo that contains env varsghv_env
- An entry in Github actions variablesdot_env
- An entry in Github secretsgcp_secret_env
- The path to a JSON format secret in GCP
Then hook it up in your docker-compose.yaml
file like:
version: '3.9'
services:
app:
env_file: .env
These environment variables are merged to the .env
file quoted in the following order:
- Terraform-passed env vars (This is not optional nor customizable)
- Repository checked-in env vars -
repo_env
file as default. (KEY=VALUE
style) - Github Secret - Create a secret named
DOT_ENV
- (KEY=VALUE
style) - GCP Secret - JSON style like
'{"key":"value"}'
Create .github/workflow/deploy.yaml
with the following content to enable an automatic build on all pushes to main
in your repo:
name: Basic deploy
on:
push:
branches: [ main ]
jobs:
EC2-Deploy:
runs-on: ubuntu-latest
steps:
- id: deploy
uses: bitovi/[email protected]
with:
gcp_access_key_id: ${{ secrets.GCP_ACCESS_KEY_ID }}
gcp_default_region: us-east-1
dot_env: ${{ secrets.DOT_ENV }}
name: Advanced deploy
on:
push:
branches: [ main ]
permissions:
contents: read
jobs:
EC2-Deploy:
runs-on: ubuntu-latest
environment:
name: ${{ github.ref_name }}
url: ${{ steps.deploy.outputs.vm_url }}
steps:
- id: deploy
name: Deploy
uses: bitovi/[email protected]
with:
gcp_access_key_id: ${{ secrets.GCP_ACCESS_KEY_ID }}
gcp_default_region: us-east-1
domain_name: bitovi.com
sub_domain: app
tf_state_bucket: my-terraform-state-bucket
dot_env: ${{ secrets.DOT_ENV }}
ghv_env: ${{ vars.VARS }}
app_port: 3000
additional_tags: "{\"key1\": \"value1\",\"key2\": \"value2\"}"
The following inputs can be used as step.with
keys
Name | Type | Description |
---|---|---|
checkout |
Boolean | Set to false if the code is already checked out (Default is true ) (Optional) |
gcp_access_key_id |
String | GCP access key ID |
gcp_default_region |
String | GCP default region |
gcp_image_id |
String | GCP Machine Image ID. Will default to latest Ubuntu 22.04 server image (HVM). Accepts ami-#### values |
domain_name |
String | Define the root domain name for the application. e.g. bitovi.com' |
sub_domain |
String | Define the sub-domain part of the URL. Defaults to ${org}-${repo}-{branch} |
root_domain |
Boolean | Deploy application to root domain. Will create root and www records. Defaults to false |
cert_arn |
String | Define the certificate ARN to use for the application. See note |
create_root_cert |
Boolean | Generates and manage the root cert for the application. See note. Defaults to false |
create_sub_cert |
Boolean | Generates and manage the sub-domain certificate for the application. See note. Defaults to false |
no_cert |
Boolean | Set this to true if no certificate is present for the domain. See note. Defaults to false |
tf_state_bucket |
String | GCP Cloud Storage bucket to use for Terraform state. |
tf_state_bucket_destroy |
Boolean | Force purge and deletion of Cloud Storage bucket. Any file contained there will be destroyed. (Default is false ). stack_destroy must also be true |
repo_env |
String | .env file containing environment variables to be used with the app. Name defaults to repo_env . Check Environment variables note |
dot_env |
String | .env file to be used with the app. This is the name of the Github secret. Check Environment variables note |
ghv_env |
String | .env file to be used with the app. This is the name of the Github variables. Check Environment variables note |
GCP_secret_env |
String | Secret name to pull environment variables from GCP Secret Manager. Check Environment variables note |
app_port |
String | port to expose for the app |
lb_port |
String | Load balancer listening port. Defaults to 80 if NO FQDN provided, 443 if FQDN provided |
lb_healthcheck |
String | Load balancer health check string. Defaults to HTTP:app_port |
gvm_instance_profile |
String | The GCP IAM instance profile to use for the GCP VM instance. Default is ${GITHUB_ORG_NAME}-${GITHUB_REPO_NAME}-${GITHUB_BRANCH_NAME} |
gvm_instance_type |
String | The GCP IAM instance type to use. Default is t2.small. See [this list](TODO: UPDATE) for reference |
stack_destroy |
String | Set to true to destroy the stack. Default is "" - Will delete the elb_logs bucket after the destroy action runs. |
GCP_resource_identifier |
String | Set to override the GCP resource identifier for the deployment. Defaults to ${org}-{repo}-{branch} . Use with destroy to destroy specific resources. |
app_directory |
String | Relative path for the directory of the app (i.e. where Dockerfile and docker-compose.yaml files are located). This is the directory that is copied to the EC2 instance. Default is the root of the repo. |
create_keypair_sm_entry |
Boolean | Generates and manage a secret manager entry that contains the public and private keys created for the ec2 instance. |
additional_tags |
JSON | Add additional tags to the terraform default tags, any tags put here will be added to all provisioned resources. |
Most resources will contain the tag GITHUB_ORG-GITHUB_REPO-GITHUB_BRANCH, some of them, even the resource name after. We limit this to a 60 characters string because some GCP resources have a length limit and short it if needed.
We use the kubernetes style for this. For example, kubernetes -> k(# of characters)s -> k8s. And so you might see some compressions are made.
For some specific resources, we have a 32 characters limit. If the identifier length exceeds this number after compression, we remove the middle part and replace it for a hash made up from the string itself.
Buckets names can be made of up to 63 characters. If the length allows us to add -tf-state, we will do so. If not, a simple -tf will be added.
As a default, the application will be deployed and the public URL will be displayed.
If domain_name
is defined, we will look up for a certificate with the name of that domain (eg. example.com
). We expect that certificate to contain both example.com
and *.example.com
.
If you wish to set up domain_name
and disable the certificate lookup, set up no_cert
to true.
Setting create_root_cert
to true
will create this certificate with both example.com
and *.example.com
for you, and validate them. (DNS validation).
Setting create_sub_cert
to true
will create a certificate just for the subdomain, and validate it.
To change a certificate (root_cert, sub_cert, ARN or pre-existing root cert), you must first set the no_cert
flag to true, run the action, then set the no_cert
flag to false, add the desired settings and excecute the action again. (This will destroy the first certificate.)
This is necessary due to a limitation that prevents certificates from being changed while in use by certain resources.
BitOps allows you to define Infrastructure-as-Code for multiple tools in a central place. This action uses a BitOps Operations Repository to set up the necessary Terraform and Ansible to create infrastructure and deploy to it.
We would love for you to contribute to bitovi/github-actions-deploy-docker-to-ec2!.
Issues and Pull Requests are welcome!
The scripts and documentation in this project are released under the MIT License.
Bitovi is a proud supporter of Open Source software.
You can get help or ask questions on Discord channel! Come hangout with us!
Or, you can hire us for training, consulting, or development. Set up a free consultation.