Overview
SanMarcSoft uses Scaleway Serverless Containers (fr-par region) for backend services. Containers are deployed via Pulumi using the pulumi-scaleway-lib shared library. Images are pushed to Scaleway Container Registry via Skopeo (zero Docker daemon).
Architecture
flake.nix (Nix build)
-> docker-archive tarball
-> skopeo copy to rg.fr-par.scw.cloud/sanmarcsoft/
-> Pulumi provisions Scaleway Serverless Container
-> Container pulls from registry on deploy
Prerequisites
- Scaleway API keys:
pass sanmarcsoft/scaleway/access-keyandpass sanmarcsoft/scaleway/api-secret - Pulumi state backend configured for Scaleway Object Storage
- Skopeo installed (available in Nix dev shell)
- Nix with flakes enabled
Procedure: Deploy a Service
Step 1: Build the OCI Image
| |
This produces a docker-archive tarball at ./result.
Step 2: Push to Scaleway Container Registry
| |
Important: The Scaleway Container Registry uses nologin as the username and the Scaleway API secret key as the password.
Step 3: Deploy via Pulumi
| |
The Pulumi stack uses the ContainerService component from pulumi-scaleway-lib which provisions:
- Scaleway Serverless Container namespace
- Container deployment referencing the registry image
- Environment variables and secrets
- Custom domain CNAME (if configured)
Step 4: Verify Deployment
| |
Container Configuration
Environment Variables
Environment variables are set in the Pulumi stack configuration. Secrets should use pulumi config set --secret.
| |
Bun Runtime Fix
Scaleway Serverless Containers with Bun runtime may fail to start if the entrypoint uses #!/usr/bin/env bun. In Nix-built images, shebangs are rewritten to absolute Nix store paths, which resolves this issue. However, if using traditional Docker builds:
Problem: Container starts but crashes immediately with “bun: not found”
Solution: Use an explicit entrypoint in the container config:
| |
Cold Start Behavior
Scaleway Serverless Containers scale to zero by default (minScale: 0). Cold starts can take 2-10 seconds depending on image size.
For latency-sensitive services: Set minScale: 1 in the Pulumi config to keep at least one instance warm.
For cost optimization: Keep minScale: 0 and implement a health check endpoint that can be pinged by an uptime monitor to keep the container warm during business hours.
Error State Diagnosis
Container Status: “error”
When a Scaleway container shows status “error”:
- Check container logs:
| |
Common causes:
- Image not found in registry (wrong tag or deleted)
- Port mismatch (container exposes different port than configured)
- Entrypoint crash (missing binary, permission error)
- Memory limit exceeded during startup
Resolution steps:
- Verify image exists:
skopeo inspect docker://rg.fr-par.scw.cloud/sanmarcsoft/<name>:<tag> --creds "nologin:$(pass sanmarcsoft/scaleway/api-secret)" - Re-push image if missing
- Re-deploy with
pulumi up - If container is stuck in error state, delete and recreate via Pulumi
- Verify image exists:
Container Status: “ready” but returning 502
The container is deployed but the application inside is not serving correctly:
- Check the port configuration matches the application’s listening port
- Verify health check endpoint responds
- Check if the application requires environment variables that are not set
- Review application logs via Scaleway console or API
Registry Management
List Images in Registry
| |
Inspect Image Metadata
| |
Retag Image (testing -> production)
| |
Troubleshooting
- “unauthorized” on push: Verify Scaleway API secret is current. Regenerate if needed via Scaleway console.
- Image architecture mismatch: Ensure
nix buildtargetsx86_64-linux. Scaleway containers run on x86_64. - Container stuck in “creating”: Wait 2-3 minutes. If still stuck, check Scaleway status page for regional issues.
- DNS not resolving: After Pulumi deploy, CNAME records may take a few minutes to propagate. Use
digto verify.