Deploy an HTTP Container with Terraform

HTTP containers are long-running services that accept incoming web traffic. Bahriya provisions a public hostname with TLS, runs health checks, and autoscales your container across one or more regions.

Updated 23 Jun 20263 min read

HTTP containers are long-running services that accept incoming web traffic. Bahriya provisions a public hostname with TLS, runs health checks, and autoscales your container across one or more regions.

Required fields

FieldTypeExampleDescription
handlestring"api"Permanent identifier. Used in hostnames.
namestring"API Server"Display name.
imagestring"nginx:alpine"Full image reference including tag.
containerportstring"8080"The port your application listens on.
healthcheckpathstring"/healthz"HTTP path for health probes. Your app must respond 200 here, or the deploy will fail.
mincpustring"100"Guaranteed CPU in millicores.
minmemorystring"128"Guaranteed memory in megabytes.
autoscalingminreplicasstring"1"Minimum number of running instances.
activeregionslist["falkenstein-1"]One or more regions to deploy to.
projectstringbahriya_project.x.idThe project UUID (not handle).

Important: The containerport and healthcheckpath fields are critical. If your container does not respond with a 200 status at the configured port and path, the deploy will time out and the container will reach an error state.

Minimal example

resource "bahriya_project" "app" {
  handle  = "my-app"
  name    = "My Application"
  regions = ["falkenstein-1"]
}
 
resource "bahriya_container" "web" {
  handle          = "web"
  name            = "Web Server"
  image           = "nginx:alpine"
  containerport   = "80"
  healthcheckpath = "/"
  mincpu          = "100"
  minmemory       = "128"
 
  autoscalingminreplicas = "1"
  activeregions          = ["falkenstein-1"]
  project                = bahriya_project.app.id
}

With autoscaling

resource "bahriya_container" "api" {
  handle          = "api"
  name            = "API Server"
  image           = "myorg/api:v2.1.0"
  containerport   = "3000"
  healthcheckpath = "/healthz"
  mincpu          = "500"
  minmemory       = "512"
 
  autoscalingminreplicas = "2"
  autoscalingmaxreplicas = "10"
 
  activeregions = ["falkenstein-1", "helsinki-1"]
  project       = bahriya_project.app.id
}

With a private registry

If your image is in a private registry, create registry credentials and reference them:

resource "bahriya_registry" "ghcr" {
  handle   = "ghcr"
  name     = "GitHub Container Registry"
  server   = "ghcr.io"
  username = var.ghcr_username
  password = var.ghcr_token
}
 
resource "bahriya_container" "api" {
  handle          = "api"
  name            = "API Server"
  image           = "ghcr.io/myorg/api:v2.1.0"
  containerport   = "3000"
  healthcheckpath = "/healthz"
  mincpu          = "500"
  minmemory       = "512"
 
  autoscalingminreplicas = "2"
  activeregions          = ["falkenstein-1"]
  project                = bahriya_project.app.id
  registry               = bahriya_registry.ghcr.handle
}

With environment variables and secrets

resource "bahriya_secret" "db_password" {
  handle = "db-password"
  name   = "Database Password"
  value  = var.db_password
}
 
resource "bahriya_container" "api" {
  handle          = "api"
  name            = "API Server"
  image           = "myorg/api:v2.1.0"
  containerport   = "3000"
  healthcheckpath = "/healthz"
  mincpu          = "500"
  minmemory       = "512"
 
  autoscalingminreplicas = "2"
  activeregions          = ["falkenstein-1"]
  project                = bahriya_project.app.id
 
  newenvvar {
    key   = "NODE_ENV"
    value = "production"
  }
 
  newenvvar {
    key   = "LOG_LEVEL"
    value = "info"
  }
 
  secretsenvvar {
    secret = bahriya_secret.db_password.handle
    name   = "DATABASE_PASSWORD"
  }
}

With custom hostnames

resource "bahriya_container" "web" {
  handle          = "web"
  name            = "Website"
  image           = "myorg/web:latest"
  containerport   = "3000"
  healthcheckpath = "/"
  mincpu          = "250"
  minmemory       = "256"
 
  autoscalingminreplicas = "1"
  activeregions          = ["falkenstein-1"]
  project                = bahriya_project.app.id
 
  hostnames {
    hostname = "www.example.com"
  }
}

Point a CNAME record for www.example.com to the target shown in the console. TLS is provisioned automatically.

Outputs

AttributeDescription
idContainer UUID.
statusCurrent status (running, provisioning, error, etc.).
defaulthostnameThe system-generated hostname identifier.
output "api_status" {
  value = bahriya_container.api.status
}

Common mistakes

SymptomCauseFix
Container reaches error after deployHealth check fails — wrong port or pathSet containerport to the port your app listens on, and healthcheckpath to a path that returns 200.
Unknown attribute errorUsing snake_case (container_port)Use the flat name: containerport.
Project reference rejectedPassing .handle instead of .idUse bahriya_project.x.id.