App Deployment #

This guide describes how to deploy a container image to use with an app.

Apps run in Docker containers based on images stored in a Docker registry. We provide this registry for you. Pushing images to the registry happens by tagging an image with the name of the registry and a tag which identifies your image version. The image version tag could be an assigned version like v1.0.0 or simply a Git commit hash from a CI build. This tag is marked <IMAGETAG> in the following sections.

We also assume that there is an Organization <ORGANIZATION>, a Project <PROJECT> and a Stage <STAGE> with an App named <APPNAME>.

Refer to the stages and apps guides for instructions on how to create those.

Deploying a container image to SetOps requires two steps.

Pushing the container image #

The easiest way to push a container image to the SetOps provided registry is to use the image:push command since it (optionally) builds the container image, correctly tags it and pushes it. You can also run the different steps manually, of course. There are different scenarios in which you can use image:push:

With an existing local image #

If you have build an image in your local machine already, you simply need to provide either the sha256 hash or your local tag.

# with sha256 hash
setops -p <PROJECT> -s <STAGE> --app <APPNAME> image:push --tag <IMAGETAG> sha256:2b51cdaabcdc9c35b36e998ec81d2ed8507def0e4709a4d5003414e727e67fa9

# with local tag
setops -p <PROJECT> -s <STAGE> --app <APPNAME> image:push --tag <IMAGETAG> my-local-image-tag

With an existing image from other registries #

You can also pull an image from other registries. Just specify the image name as you would do with docker pull.

setops -p <PROJECT> -s <STAGE> --app <APPNAME> image:push --tag <IMAGETAG> --from-image gitpod/openvscode-server:latest

If the remote image was pulled earlier on your local machine, but you would like to pull it again from the remote registry, add the --no-cache flag to the above command.

Building an image with Docker #

You can also build the image from a Dockerfile. Use --docker:build-arg 'build-arg' to pass build args to Docker. If your Dockerfile is not named Dockerfile or is not located in the directory’s root directory, you can specify its location with --docker:file.

setops -p <PROJECT> -s <STAGE> --app <APPNAME> image:push --tag <IMAGETAG> --build-with-docker /path/to/build-context [--docker:build-arg 'build-arg'] [--docker:file '/path/to/dockerfile']

# e.g.
setops -p <PROJECT> -s <STAGE> --app <APPNAME> image:push --tag <IMAGETAG> --build-with-docker /path/to/build-context --docker:build-arg 'RAILS_ENV=production' --docker:file './MyCustomDockerfile' .

To ignore any cached data when building the image use the --no-cache flag. This can be helpful if you encounter any problems during the build, e.g caused by platform issues or interfering existing data.

setops -p <PROJECT> -s <STAGE> --app <APPNAME> image:push --tag <IMAGETAG> --build-with-docker --docker:file './MyCustomDockerfile' . --no-cache

Building an image with pack CLI #

Another way to build your image locally is pack CLI. In order to build with pack, make sure you have pack CLI installed on your system. --pack:builder specifies the builder to be used to create the image. It defaults to the popular heroku/buildpacks:20. With --pack:buildpack you can specify one or multiple buildpacks to be used with pack. You can also provide ENVs on buildtime with either --pack:env KEY=VALUE (can be used multiple times) or reference an ENV file with --pack:env-file. To ignore any cached data when building the image use the --no-cache flag.

setops -p <PROJECT> -s <STAGE> --app <APPNAME> image:push --tag <IMAGETAG> --build-with-pack /path/to/build-context [--pack:builder 'builder'] [--pack:buildpack 'buildpack'] [--pack:env 'KEY=VALUE'] [--pack:env-file '/path/to/env/file']

# e.g.
setops -p <PROJECT> -s <STAGE> --app <APPNAME> image:push --tag <IMAGETAG> --build-with-pack . --pack:builder heroku/buildpacks:20 --pack:env 'RAILS_ENV=production' --pack:env 'RACK_ENV=production'

Using the new container image #

List container images #

Using the command image you can list all available images:

setops -p <PROJECT> -s <STAGE> --app <APPNAME> image
+------------+-------------------------------------------------------------------------+
|    TAGS    |                                 DIGEST                                  |
+------------+-------------------------------------------------------------------------+
| <IMAGETAG> | sha256:1745e9c1b1588c85b2fa4b120227ab156699516c16c1620142df9dde42e224cc |
+------------+-------------------------------------------------------------------------+

Run a pre-deploy one-off task #

If you’re about to deploy a new version of an application and need to run a command before starting the new version, e.g. running migrations, you can do so by running a one-off task after pushing the image.

setops -p <PROJECT> -s <STAGE> --app <APPNAME> task:run --image-tag <IMAGETAG> -- rake db:migrate

For further information see One-Off Tasks.

Deploy the new application version #

To trigger a deployment for your app container, provide the previously pushed image tag(s) to stage:apply:

setops -p <PROJECT> -s <STAGE> stage:apply --image-tags <APPNAME>=<IMAGETAG>

# or if you have multiple apps in one stage
setops -p <PROJECT> -s <STAGE> stage:apply --image-tags <APPNAME>=<IMAGETAG> <APPNAME2>=<IMAGETAG>

Runtime Status #

Once the App is deployed, you can view its current runtime status by running task:

setops -p <PROJECT> -s <STAGE> --app <APPNAME> task
App Tasks:

   1 of 1 desired tasks active

   ID                                 Image         Last Status   Health Status   Started At                  Stopped At
   5c05b59e809e40c598d9073f5cf98fa4   <IMAGENAME>   RUNNING       HEALTHY         2023-04-14T19:32:05+02:00   -


One-Off Tasks:

  None

The App Task section describes the number of active, desired and pending tasks.

When the App is running correctly, the number of desired tasks and running tasks should be equal. Note that not active tasks are not automatically pending. Thus, pending does not have to be equal to the difference between desired and active tasks.

Your App will usually have one task per instance. The number of instances can be configured via scale in the App configuration.

The Tasks section lists specific information for each individual task:

  • ID: Unique identifier for this task, for example for querying logs
  • Image: Image identifier
  • Last Status: Container runtime status, can be one of:
    • PROVISIONING – additional steps are performed before a task can be launched, e.g. network interface provisioning
    • PENDING – waiting on the container agent to take further action
    • ACTIVATING – need to perform additional steps after the task is launched but before the task can transition to the RUNNING state
    • RUNNING – task is successfully running
    • DEACTIVATING – need to perform additional steps before the task is stopped, e.g. load balancer target group de-registration
    • STOPPING – waiting on the container agent to take further action
    • DEPROVISIONING – need to perform additional steps after the task has stopped but before the task transitions to the STOPPED state
    • STOPPED – task has been successfully stopped
  • Health Status: Container Health Check status, can be one of:
    • HEALTHY – container Health Check has passed successfully
    • UNHEALTHY – container Health Check has failed
    • UNKNOWN – container Health Check is being evaluated or there is no container Health Check defined
  • Started At: when the task was started
  • Stopped At: when the task was stopped (for terminating tasks, optional)