Skip to main content

Hashicorp Waypoint with Docker

Shen Zhen, China

Waypoint is a tool that enables developers to describe how to get their applications from development to production in a single file and deploy using a single command: waypoint up. After deployment, Waypoint provides tools such as logs, exec, and more to validate and debug any deployments. Waypoint is fully extensible based on a plugin system which allows Waypoint to work with any tools and platforms.

Installation

wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | tee /usr/share/keyrings/hashicorp-archive-keyring.gpg

echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/hashicorp.list

apt update && apt install waypoint

Validate the installation by running the waypoint command:

waypoint -version
CLI: v0.8.1 (622f37bd1)

As this is an older version I will download the binary and overwrite the installed version:

wget https://releases.hashicorp.com/waypoint/0.9.0/waypoint_0.9.0_linux_amd64.zip
unzip waypoint_0.9.0_linux_amd64.zip
rm /usr/bin/waypoint
mv ./waypoint /usr/bin/waypoint
chmod +x /usr/bin/waypoint
waypoint -version
CLI: v0.9.0 (2a7b89036)

Use Waypoint with Docker (Next.js)

I am following the getting started guide by Hashicorp to set up an Next.js app inside a Docker container using waypoint. The Example code can be found on Github. Start by cloning the Waypoint Examples repository and navigate to the Next.js example:

git clone https://github.com/hashicorp/waypoint-examples.git
cd waypoint-examples/docker/next-js

According to the documentation this only works with Docker Desktop. Which would be a Problem when I want to use this on a Debian server ? But let's give it a try and see what happens..

Run the following command to install the Waypoint server. The -accept-tos flag confirms that you accept the terms of service:

waypoint install -platform=docker -accept-tos

Now this looks promising:

✓ Pulling image: hashicorp/waypoint:latest
✓ Installing Waypoint server to docker
✓ Server container started!
✓ Server installed and configured!
✓ Successfully connected to Waypoint server in Docker!
✓ Runner "static" installed
✓ Registered ondemand runner!
✓ Waypoint runner installed and started!
✓ Runner "static" adopted successfully.
Waypoint server successfully installed and configured!

The CLI has been configured to connect to the server automatically. This
connection information is saved in the CLI context named "install-1658472038".
Use the "waypoint context" CLI to manage CLI contexts.

The server has been configured to advertise the following address for
entrypoint communications. This must be a reachable address for all your
deployments. If this is incorrect, manually set it using the CLI command
"waypoint server config-set".

To launch and authenticate into the Web UI, run:
waypoint ui -authenticate

Advertise Address: waypoint-server:9701
Web UI Address: https://localhost:9702

Waypoint UI

I did not use the waypoint server config-set command but directly opened the waypoint-server:9702 address:

Hashicorp Waypoint

Clicking on authentication leads me to the following page where I am supposed to create an access token for the UI:

waypoint user token

HZCwuUtmrrpVKaLUHPhE6ynePphYJsn66qvryWmYv6TmSRPnQ134VyvHNrYZRdFz6ecsjM4fSwnc3HRApzS8cuDmNFp2cntVjurDTCi5pWGRXbRWRPWYtzUj1ypvzvyafNpfwpVQaQ31ftD8jDn3haskEqF4wKgKHRdi

Hashicorp Waypoint

Here I am greeted with a deprecation warning for the next version of Waypoint:

Upcoming changes to projects In our upcoming Waypoint 0.10 release, we will be removing "projects" from Waypoint. With this change, all projects settings and variables will be assigned directly to applications. To learn more about this change, visit the link.

Waypoint Job Configuration

When you deploy your app with Waypoint, your computer (the Waypoint client) connects to the Waypoint server to initiate the Waypoint workflow. The client then registers itself as a runner, allowing Waypoint to run builds on it. Before you can build and deploy your application, you must initialize it with Waypoint. For a blank application, this is done with the init command.

When you initialize Waypoint for your application, Waypoint first looks to see if there is a Waypoint configuration file (waypoint.hcl) for the application in the current directory. If Waypoint cannot find the application's configuration file when you run waypoint init, Waypoint will create a starter waypoint.hcl file that you can then customize for your application. Here is the configuration file for the Next.js project:

cat waypoint.hcl

project = "example-nextjs"

app "example-nextjs" {
 labels = {
   "service" = "example-nextjs",
   "env"     = "dev"
 }

 build {
   use "pack" {}
 }

 deploy {
   use "docker" {}
 }
}

The build clause defines how Waypoint will build the app. pack tells Waypoint to use the most relevant Cloud Native Buildpack to build the application. If the app is written in NodeJS, Waypoint will use NodeJS Cloud Native Buildpacks, etc.

  • deploy clause defines how Waypoint will deploy the app. The docker option tells Waypoint to deploy the application to Docker.

Initialize Waypoint for the Example App

Run the init command to initialize the application:

waypoint init

✓ Configuration file appears valid
✓ Connection to Waypoint server was successful
✓ Project "example-nextjs" and all apps are registered with the server.

Project initialized!

You may now call 'waypoint up' to deploy your project or
commands such as 'waypoint build' to perform steps individually.

Build and Deploy

This application is configured to use Heroku Buildpacks to detect the type of application running and to launch it within Docker. Because Waypoint uses the applicable buildpack to create the Dockerfile, you do not need to create the file yourself.

Once Waypoint completes the build, it stores the artifacts in either a local or remote registry. The registry clause in the waypoint.hcl file specifies where to store the app's artifacts. If the registry clause is not present, Waypoint will default to using the local Docker instance to store the application's artifacts.

Deploy the application to Docker Desktop by running:

waypoint up

Here I am ending in an error message:

Hashicorp Waypoint

 │ [builder]   opensslErrorStack: [ 'error:03000086:digital envelope routines::init
 │ ialization error' ],
 │ [builder]   library: 'digital envelope routines',
 │ [builder]   reason: 'unsupported',
 │ [builder]   code: 'ERR_OSSL_EVP_UNSUPPORTED'
 │ [builder] }
 │ [builder]
 │ [builder] Node.js v18.5.0
 │ [builder] error Command failed with exit code 1.
 │ [builder] ERROR: failed to build: exit status 1

This is an issue with OpenSSL in Node.js I encountered before in a Gatby.js project. This could be solved by using the OpenSSL Legacy Provider in the projects package.json:

"scripts": {
  "dev": "SET NODE_OPTIONS=--openssl-legacy-provider && next dev",
  "build": "SET NODE_OPTIONS=--openssl-legacy-provider && next build",
  "start": "SET NODE_OPTIONS=--openssl-legacy-provider && next start"
}

So now I get a little farther but run into another issue - a permission error for the build script:

[builder] /cnb/buildpacks/heroku_nodejs-yarn/0.2.3/lib/build.sh: line 129: /layers/heroku_nodejs-yarn/toolbox/bin/yj: Permission denied
[builder] ERROR: failed to build: exit status 126
executing lifecycle. This may be the result of using an untrusted builder: failed with status code: 51

I found the file and used chmod to opened up the permissions - let's see if this is really the issue:

/var/lib/docker/overlay2/8ed3f11989f7d6778af530e5126169a0241e8fa00667dd20a07e87fda476c2eb/diff/cnb/buildpacks/heroku_nodejs-yarn/0.2.3/lib

-rwxrwxrwx 1 root root 4290 Jan  1  1980 build.sh
-rwxrwxrwx 1 root root  280 Jan  1  1980 detect.sh
drwxr-xr-x 2 root root 4096 Jan  1  1980 utils

And another error message:

[builder] $ SET NODE_OPTIONS=--openssl-legacy-provider && next build
[builder] /bin/sh: 1: SET: not found
[builder] error Command failed with exit code 127.
[builder] info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
[builder] ERROR: failed to build: exit status 127
executing lifecycle. This may be the result of using an untrusted builder: failed with status code: 51

Use Waypoint with Docker (Go)

Ok enough Node.js shenanigans... let's try another example. The Go example is a simple file server that serves files on port 3000:

package main

import (
        "fmt"
        "log"
        "net/http"
)

func main() {
        fileServer := http.FileServer(http.Dir("./static"))
        http.Handle("/", fileServer)

        fmt.Printf("Starting server at: http://localhost:3000\n")
        if err := http.ListenAndServe(":3000", nil); err != nil {
                log.Fatal(err)
        }
}

The job file for it is basically identical to the previous one:

project = "example-go"

app "example-go" {
  labels = {
    "service" = "example-go",
    "env"     = "dev"
  }

  build {
    use "pack" {}
  }

  deploy {
    use "docker" {}
  }
}

Run a Deployment

So let's initialize and run the example code:

waypoint init
waypoint up

This time the build worked:

Hashicorp Waypoint

docker ps

IMAGE             PORTS                                       NAMES
example-go:latest 0.0.0.0:49153->3000/tcp, :::49153->3000/tcp example-go-01G8MYK998Z6RRQG89YESFJ6N1

And I am able to access the web frontend on port 49153:

Hashicorp Waypoint

👍

Additionally there is a generated URL that also allows you to reach the frontend:

The deploy was successful! A Waypoint deployment URL is shown below. This
can be used internally to check your deployment and is not meant for external
traffic. You can manage this hostname using "waypoint hostname."

           URL: https://rare-borg-aardvark.waypoint.run
Deployment URL: https://rare-borg-aardvark--v1.waypoint.run

Updating a Deployment

You can edit the example html code and run waypoint again to re-deploy your app:

The deploy was successful! A Waypoint deployment URL is shown below. This
can be used internally to check your deployment and is not meant for external
traffic. You can manage this hostname using "waypoint hostname."

           URL: https://rare-borg-aardvark.waypoint.run
Deployment URL: https://rare-borg-aardvark--v2.waypoint.run

Hashicorp Waypoint

This time the generated URL fails:

Couldn't find a Waypoint deployment with this URL: If you expected to see a deployment here you might want to check your logs to see if something went wrong.

But I am able to access the frontend locally through the assigned port 0.0.0.0:49154->3000/tcp, :::49154->3000/tcp:

Hashicorp Waypoint

Debugging a Deployment

You can use the following command to get the deployment logs:

waypoint logs

And here we have the reason why the URL is not working - some networking issue:

2022-07-23T07:49:52.850Z QAG4GY: Starting server at: http://localhost:3000
2022-07-23T07:50:02.348Z QAG4GY: [WARN]  entrypoint.config.watcher: error starting URL service: err="error
discovering network endpoints: Get "https://control.hzn.network/.well-known/horizon/hubs.json": dial tcp: lookup
control.hzn.network on 127.0.0.11:53: read udp 127.0.0.1:52624->127.0.0.11:53: i/o timeout"

Destroying a Deployment

Run destroy to remove the application from Docker:

waypoint destroy -auto-approve
Performing operation locally

» Destroying releases for application 'example-go'...
✓ Running release destroy v2
✓ Running release destroy v1

» Destroying deployments for application 'example-go'...
✓ Running deployment destroy v2
✓ Deleting container: 7d2ab16ff4e389a1b503de787b3f97c1e5e62e993a58bea8f2ee3e222fce4144
✓ Running deployment destroy v1
✓ Deleting container: d283cb3d0dcd98db3510a1a869f95da97454bf51b4ae0186df9700a7ec6ca80a
Destroy successful!