After building multiarch Docker containers for Rust applications, you want to deploy them somewhere. Scaleway’s serverless container platform offers a straightforward way to run containers without managing infrastructure, and OpenTofu provides the infrastructure-as-code tooling. This guide walks through deploying Docker containers to Scaleway using the OpenTofu provider, from setting up the registry to running your container.
Prerequisites
Before we start, you’ll need:
- A Scaleway account with API credentials
- OpenTofu installed on your system
- Of course, Docker installed for building and pushing images
- A Docker image; for example Rocket and Rust.
Installing OpenTofu
OpenTofu is an open-source fork of Terraform that provides infrastructure-as-code capabilities.
# Install OpenTofu on macOS with Homebrew
$ > brew install opentofu
Let’s verify the installation worked:
$ > tofu version
OpenTofu v1.9.0
on darwin_arm64
Setting Up Scaleway Credentials
First things first, you’ll need to create API credentials in the Scaleway console. Once you’ve got them, we can store them as environment variables.
$ > export SCW_ACCESS_KEY="your-access-key"
$ > export SCW_SECRET_KEY="your-secret-key"
$ > export SCW_DEFAULT_REGION="fr-par"
$ > export SCW_DEFAULT_PROJECT_ID="your-project-id"
$ > export SCW_DEFAULT_ORGANIZATION_ID="your-organization-id"
This will use the Paris location in France for the running container.
Creating the Container Registry
Next, create an OpenTofu configuration file main.tf for a container registry to store the Docker image
terraform {
required_providers {
scaleway = {
source = "scaleway/scaleway"
version = "~> 2.64"
}
}
required_version = ">= 0.13"
}
provider "scaleway" { }
resource "scaleway_container_namespace" "main" {
name = "rocket-example"
description = "test container"
}
output "container_registry" {
value = "${scaleway_container_namespace.main.registry_endpoint}"
description = "Registry endpoint for the container"
}
Now let’s initialise OpenTofu and plan the registry:
$ > tofu init
[…]
OpenTofu has been successfully initialised!
$ > tofu plan
[…]
Have a quick look at the plan to see what’ll be created, then apply it:
$ > tofu apply tfplan
scaleway_registry_namespace.main: Creating...
scaleway_registry_namespace.main: Creation complete after 2s
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Outputs:
container_registry = "rg.fr-par.scw.cloud/funcscwrocketexampler5etvjil"
The container registry is needed in the next step for tagging and pushing the Docker container.
Building and Pushing Docker Images
With the registry created, we can now build and push the Docker image. For Scaleway, you’ll need to push a architecture-specific image for amd64 platform. Here’s how to do it:
# Build for ARM64 (Scaleway only supports amd64)
$ > docker build \
--platform linux/amd64 \
-f Dockerfile . \
-t rg.fr-par.scw.cloud/funcscwrocketexampler5etvjil/application:latest-amd64
# Authenticate with Scaleway registry using the CLI
$ > scw registry login
The CLI generates a temporary token and configures Docker authentication automatically. Once that’s done, you can push the image:
$ > docker push rg.fr-par.scw.cloud/funcscwrocketexampler5etvjil/application:latest-amd64
Deploying the Container
Now comes deploying the container; add the container resource to the OpenTofu configuration. Here’s the updated main.tf with the container:
terraform {
required_providers {
scaleway = {
source = "scaleway/scaleway"
version = "~> 2.64"
}
}
required_version = ">= 0.13"
}
provider "scaleway" { }
resource "scaleway_container_namespace" "main" {
name = "rocket-example"
description = "test container"
}
output "container_registry" {
value = "${scaleway_container_namespace.main.registry_endpoint}"
description = "Registry endpoint for the container"
}
resource "scaleway_container" "main" {
name = "application"
namespace_id = scaleway_container_namespace.main.id
registry_image = "${scaleway_container_namespace.main.registry_endpoint}/application:latest-amd64"
port = 8080
cpu_limit = 256
memory_limit = 512
min_scale = 1
max_scale = 1
environment_variables = {
ROCKET_LOG_LEVEL = "debug"
ROCKET_ADDRESS = "0.0.0.0"
ROCKET_PORT = "8080"
}
privacy = "public"
deploy = true
}
output "container_url" {
value = scaleway_container.main.domain_name
description = "Public URL for the container"
}
Apply the configuration and watch it deploy:
$ > tofu apply
scaleway_container_namespace.main: Creating...
scaleway_container_namespace.main: Creation complete after 2s
scaleway_container.main: Creating...
scaleway_container.main: Creation complete after 15s
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Outputs:
container_registry = "rg.fr-par.scw.cloud/funcscwrocketexampler5etvjil"
container_url = "rocketexampler5etvjil-application.functions.fnc.fr-par.scw.cloud"
Verifying the Deployment
Time to see if everything’s working! Let’s test the deployed container:
$ > curl https://rocketexampler5etvjil-application.functions.fnc.fr-par.scw.cloud/
Hello, World! API is running.
You can also check the container status using the Scaleway CLI:
$ > scw container container list
ID NAME NAMESPACE ID STATUS MIN SCALE
0e118806-70a4-43c9-9794-7cf35fdd943d application e10e600c-b00c-452c-923a-1d6e1552cff5 ready 1
Cleanup
When you’re done experimenting or need to clean up, removing all resources is straightforward:
$ > tofu destroy
This removes the container and registry namespace.
That’s It! 🎉
Working with Scaleway and OpenTofu for container deployments was a nice journey; still prefer a programmatic approach like the AWS Cloud Development Kit over OpenTofu and Terraform. But it works …