Deploy a self-hosted service straight from its public Docker image, without writing a Dockerfile or maintaining a build process yourself. Use this approach when the service you need already ships an official, production-ready image.
Unlike Upsun’s other app types, which build your repository code into a runtime image, a Docker image app skips that build step: you provide an already-built image, and Upsun deploys it exactly as-is.
If you already configure environment variables, mounts, or service relationships for other apps in your project, you can do the same for a Docker image app, with the adjustments noted in Mounts and Environment variables.
Verified examples
The following services are verified to run on Upsun using the ready-to-use configuration provided in the corresponding topic.
Before you begin
-
Install the Upsun CLI.
-
Run the following commands to log in and connect the current Git repository to the correct Upsun project. Replace
<PROJECT_ID> with your project ID (run upsun projects to list them).
Define each Docker image as an application in .upsun/config.yaml. At minimum:
- Set
type to docker:1.
- Set
image.name to the image tag to run. Images without a registry hostname are pulled from Docker Hub. For images from other registries, include the full registry hostname in image.name.
Add a custom start command, persistent storage, or environment variables to the same app definition as needed — see Startup commands, Mounts, and Environment variables.
Deploy an app
Commit the changes to .upsun/config.yaml and push them to Upsun:
List routes after deployment:
Startup commands
By default, Upsun runs the startup command defined by the image. $PORT typically matches the port exposed by the image.
Set web.commands.start in .upsun/config.yaml only when the image’s default command is not suitable. If you set web.commands.start:
$PORT changes to a platform-assigned value. Make sure the command indicates to listen on $PORT; otherwise, the app may listen on the wrong port and return 502 Bad Gateway errors.
- Environment variables in
web.commands.start are passed literally unless the command runs through a shell. If the image includes sh, use sh -c "..." when you need environment variable expansion.
Mounts
Any path configured under mounts must already exist as a directory in the image. Upsun does not create missing directories inside the image at runtime.
Environment variables
Variables under variables.env are exposed to the running container.
If the app connects to Upsun services, use direct service variables such as DATABASE_HOST, DATABASE_PORT, DATABASE_USERNAME, and DATABASE_PASSWORD.
Avoid relying on PLATFORM_RELATIONSHIPS inside minimal Docker images. It requires base64 and JSON parsing tools that may not exist in the image. Use direct service variables instead.
Updating the image version
Change the image tag in image.name, then rebuild and redeploy the environment.
- For fixed version tags, commit the tag change and run
upsun push.
- For
latest tags, trigger a redeploy so Upsun pulls the current image for that tag.
To redeploy from the Console: select your project, choose the environment, click More, and click Redeploy.
To redeploy from the CLI: manually trigger a build by updating an environment variable and pushing the change by running upsun push.
Debug an app over SSH
If a container fails to start, a health check fails, or the image has no shell of its own, connect over SSH to debug it:
This connects to the LXC container, the layer Upsun controls around the image, not the image’s own container (consistent with other Upsun app images). From the LXC container, you can:
-
View logs, such as
/var/log/app.log, to debug start command failures.
-
Inspect the environment around the image’s container, for example mounts, networking, and process state, without needing a shell inside the image. The process list shows whether the app’s start command is running, still starting, or crash-looping, which is the main signal available when the health check fails and the image has no shell to exec into:
-
Enter the image’s own container, if it includes a shell. Upsun cannot inject a shell into an image it does not control.
The Docker CLI is not available inside the shell. Use standard shell commands to inspect the running app.
Limitations
-
Docker image apps use pre-built images. Upsun does not build a Dockerfile from the repository for this app type.
-
Build hooks are not supported for Docker image apps.
-
Meilisearch is the only image currently verified to work on Upsun. Other public images may work but have not been tested.
-
You are responsible for updating images when image publishers release security fixes.
-
Docker images include their own filesystem and can use more project storage than Upsun’s built-in runtime images.
-
Keep images under 4 GB. Larger images require different storage handling. To use an image larger than 4 GB, create a Support ticket and provide the full image name and registry path.
To keep image size down:
- Use a minimal base image such as
alpine, distroless, or busybox.
- Avoid bundling build tools or caches into your production image.
- Use multi-stage builds to separate build and runtime layers.
Minimal images such as distroless and busybox may not include shell tools such as sh, base64, or jq. This affects startup command expansion and any logic that depends on decoding PLATFORM_RELATIONSHIPS.
Last modified on July 13, 2026