In this developer guide, we are going to cover hosting a Go application on App Platform. We will cover steps to hosting, common pitfalls, and more so that you can optimally host your Go application on App Platform. If you come across something that isn’t covered in this guide, ask a community question.
For this guide, we make the assumption that you already have a Go app.
To deploy a Go app on App Platform, you will need:
If you’re just learning App Platform, we have a sample Go app you can fork on GitHub.
Creating an app for the first time is easily done by clicking Create App in the DigitalOcean cloud control panel. Before creating an apps, it’s good to consider what things you will need to locate, build, and configure your app at both build and run time.
Some things to consider before creation:
App Platform supports two methods of build apps:
Buildpacks inspect your code and create a plan to build and run your code. When you give App Platform access to your code base, it checks your code to determine what language it is using, and if the language is supported, uses a buildpack to build, run, and deploy your code. Build packs are usually the most user-accessible way to deploy apps on App Platform.
heroku-buildpack-go is utilized as the buildpack for detecting and building your Golang applications.
When creating an app, App Platform scans the app source code in the App Platform detection service which will determine the language/framework for building your application.
App Platform looks for any of the following files to detect a Go application:
go.mod
Gopkg.toml
Godeps/Godeps.json
vendor/vendor.json
glide.yaml
If any of the above are found, App Platform will walk you through deploying your application. Providing one of the above files is the simplest and fastest way to deploy a Go app to App Platform.
If none of the above are found, App Platform will default to Dockerfile builds if a dockerfile is found in the root of the project directory.
The version in your go.mod
file is automatically detected and used as the version to build your application:
module github.com/digitalocean/sample-golang
go 1.16
...
Using a Dockerfile to build a Go app is a flexible way to optimize the build image that will be used to deploy the app. By placing a Dockerfile
in the root of the directory or specifying the path to a dockerfile in the app spec, App Platform will detect the Go app as a dockerfile based app.
One of the advantages of a Dockerfile based build is the image can be cut down really small with multi-stage builds. For example, digitalocean/sample-dockerfile uses multi-stage build so the final container image only contains updated CA certificates and the compiled Go binary:
# This is a standard Dockerfile for building a Go app.
# It is a multi-stage build: the first stage compiles the Go source into a binary, and
# the second stage copies only the binary into an alpine base.
# -- Stage 1 -- #
# Compile the app.
FROM golang:1.12-alpine as builder
WORKDIR /app
# The build context is set to the directory where the repo is cloned.
# This will copy all files in the repo to /app inside the container.
# If your app requires the build context to be set to a subdirectory inside the repo, you
# can use the source_dir app spec option, see: <https://www.digitalocean.com/docs/app-platform/references/app-specification-reference/>
COPY . .
RUN go build -mod=vendor -o bin/hello
# -- Stage 2 -- #
# Create the final environment with the compiled binary.
FROM alpine
# Install any required dependencies.
RUN apk --no-cache add ca-certificates
WORKDIR /root/
# Copy the binary from the builder stage and set it as the default command.
COPY --from=builder /app/bin/hello /usr/local/bin/
CMD ["hello"]
The process for creating an App Platform app involves four steps:
You can add more configurations, services, static sites, and databases after the initial creation if needed.
App Platform has native integration with GitHub and GitLab. App Platform also supports public pre-built images hosted in Docker Hub and DigitalOcean Container Registry.
After authenticating with GitHub or GitLab, you can select repositories and their respective branches to deploy from. You can also indicate if changes to this branch should be auto-deployed by App Platform.
During this step, App Platform scans the code base and detects the language and framework. If the source is not located in the root directory, the option to specify a sub-directory is provided after the first scan attempt. Once the Go app is detected, you can specify the following configurations:
You can create more complex configuration after creation by modifying the app’s configuration in the control panel or by editing the app’s spec.
Environment Variables are included at both run and build time by default and you can customize them in the app spec later if needed. We recommend using the Encrypt
option for secrets, such as CA certificates or SSH keys, that should not be visible after creation. This feature encrypts the value in the app spec. The secret is bound to the app and is only decrypted before injection into the app.
Typically you need environment variables for:
HTTP Port is the port that an app is expecting traffic on. If your app uses the PORT
environment variable, you can leave this as is, otherwise you can change it to match the port that is set in your app. App Platform automatically receives traffic on port 80 and 443 and forwards it to this port. If you set a PORT
environment variable during your app’s configuration in the control panel, it overwrites the PORT
environment variable in your app.
The HTTP Request Route defines the subpath that you can access this component from. If this is the only component in the app, then the request route will be the domain’s root /
. If your app has multiple public-facing components, you can define a route for each component. For example, if your app contains a frontend static site that connects to a backend API, the static site’s request route can be the domain’s root /
and the Go API can be available at /api
.
During this step, you can attach a database. App Platform offers a low cost PostgreSQL development database you can add to the app as a an additional component. You can also attach existing databases created using the Database service.
Your app can connect the app to a dev database by adding a bind variable (DATABASE_URL=${db.DATABASE_URL}
) to the app’s environment variables.
App Platform automatically detects build and run commands. If you have special arguments, you can add them in the app’s Build Command and Run Command sections.
In some cases, you can also run startup scripts before starting your Go app to get the environment ready for production.
Typically in a Go application, you’ll see:
npm run build
npm start
App names are used within a provided domain with a random five character string appended. Most apps eventually use a custom domain like example.com
instead of the provided domain. The domain provided by DigitalOcean is good for testing, though.
When you pick a region, we recommend picking one that is close to your users to minimize latency.
Lastly, you can pick your app’s hosting plan. We recommend Basic plans for simple, low traffic apps and apps early in their development. You can upgrade to a Pro tier plan at any time. Upgrading your plan does not cause any downtime. The Starter tier is reserved for deploying and hosting static websites.
Most apps can be deployed on either Basic or Pro tiers. The Pro tier provides more bandwidth and build minutes, access to dedicated CPU instances, per-minute metrics, and horizontal scaling.
Go apps cannot be static sites, so you will be using Basic and Pro tier apps.
After clicking the Launch button, the configured app builds, deploys, and is provided a domain. You can find details about the deployment in the Deployments` tab.
Some apps set the listening port using the PORT
environment variable, while others are hardcoded. In the scenario that an app uses PORT
to determine the HTTP server port, the HTTP Port
field in app’s Settings tab overwrites any PORT
environment variables that are set in the app.
If an app’s HTTP port is hardcoded, the HTTP Port
for that component needs to be changed in the Settings tab to match the app’s value.
localhost
vs 0.0.0.0
HTTP servers explicitly running on localhost
or 127.0.0.1
creates a common issue. This is problematic because localhost
is an alias for 127.0.0.1
, which is a local loopback interface that is not externally exposed to the current environment.
HTTP servers should not include an address specifying 0.0.0.0
explicitly, or using the process.env.PORT
.
If your Go app uses private dependencies that are not accessible with the same account used to access the apps, a personal access token can be injected by setting an environment variable with the key of GO_GIT_CRED__HTTPS__GITHUB__COM
and the value of a GitHub personal access token. Note, this has only been tested with GitHub. More details can be found here.
App Platform offers a number of features that can be used to secure your app:
Encrypted Environment Variables: Encrypts environment variables, which binds them to the app and makes them immutable. They are injected at both build and run time events.
Database Trusted Sources:: Limits connections to your database to specified IP addresses or resources in your DigitalOcean account.
HTTPS Encryption: Ensures all traffic is encrypted over the wire and redirects all HTTP traffic to HTTPS.
The Insights tab in the DigitalOcean Apps dashboard shows metrics for all of an apps components. Alongside seeing CPU and memory usage, Insights tracks restart counts, bandwidth, and latency metrics.
App Platform offers app alerts and metrics monitoring via email and Slack integration. You can set alerts that will trigger based on resource usage or failed deployments.
You can scale your app vertically or horizontally depending on what tier your app is being hosted on. App’s on a *Pro tier plan can be scaled horizontally by adding more load-balanced containers. Apps on a Basic tier can be scaled vertically, which increases the CPU and memory allocated to each container instance.
You can add several different types of useful components to your app as it grows in scope. Here’s brief overview of each:
Workers: Run server-side code and can’t be accessed externally from the internet. Because workers cannot accept HTTP requests, they are only suitable for doing background tasks, such as queue processing or video encoding.
Internal Services: are similar to services but expose ports internally. A service can expose external and internal ports.
Jobs: One off operations that you can schedule to run before or after a deployment, or after a deploy fails. Jobs are great for starting database migrations or executing code on a failed deployment.
Runtime logs contain the live logs for the app’s components that support logging. These logs include standard output and errors. You can access the runtime logs from the Runtime Logs tab.
In addition runtime logs, we also provide build and deployment logs for each of your app’s components. You can access build and deployment logs from the Deployments
tab in the app’s dashboard. Here you can find the build and deployment logs for each of your components for a specific deployment.
App Platform also supports log forwarding. You can forward your app runtime logs to external log management providers, like Papertrail and Datadog.
App Platform preserves logs and posts them under the deployment. You can see both the App Platform logs and your build logs as they happen and use them to troubleshoot build issues.
Deployment logs occur after a build has been successful. At this point, the container image of the app created by App Platform is being pulled from a private container registry and deployed to an App Platform cluster.
Debugging a live app offers a few more tools than the simple log offering of builds and deployments. Not only are the live logs available under the Runtime Logs tab, you can also access component instances through the console.
App Platform works well with CI/CD settings in different scenarios. You can use auto-deployment to continuously deploy changes to your app to see if they work. You can also disable auto-deploy and use GitHub Actions to deploy when certain conditions are met.
You can turn off auto-deployment and only trigger a build after tests are done, or on a new version release, or ad-hoc. Some common paths are:
All of these scenarios and more are possible.
App Platform has a GitHub Action called app_action that you can use to trigger deployments on specific types of changes to your repo, including new commits on a branch, releases, tags, and merges. It also supports dynamically updating app specs to pull specific Docker image versions.
You can perform App Platform operation in almost any CI/CD environment using the doctl
command-line tool. See the doctl
reference page for a full list of commands that you can use to manage App Platform.
See Troubleshoot Your App for more troubleshooting techniques for App Platform.