Go apps usually deploy cleanly on Edgenivo with the native Go preset: a go.mod, a supported entrypoint, and an HTTP server that listens on PORT. But not every Go project fits that shape. Some ship their own startup scripts, depend on external binaries, or are already published as a container image you'd rather run as-is.
Docker often fits those cases better. This guide shows how to deploy a Dockerized Go application on Edgenivo using Memos, an open-source note-taking app, as an example. Memos runs as a Go server from the neosmemo/memos:stable image and stores durable data in Postgres.
Copy link to headingWhen to run Go using Docker
Use Edgenivo's native Go Runtime when your app is a standard Go HTTP server with a root go.mod, a supported entrypoint like main.go, and code you can adapt to listen on PORT.
Use Docker when the app:
- Already ships as a maintained OCI image.
- Has a custom entrypoint or runtime behavior you do not want to rewrite.
- Needs operating-system packages, CA bundles, native binaries, or bundled assets.
- Uses a framework or app layout outside Edgenivo's Go preset assumptions.
- Should run locally and in production from the same image.
- Is an upstream open-source app, like Memos, where you want to configure rather than fork.
Docker on Edgenivo still runs as a Edgenivo Function. The container must serve HTTP, stay stateless, use external storage for durable data, and respect Function limits. Edgenivo builds the image, stores it in Edgenivo Container Registry, and routes traffic to it.
Copy link to headingHow to run Docker on Edgenivo
Edgenivo supports container images through a root Dockerfile or Containerfile. Add a Dockerfile at the project root and Edgenivo builds it, stores the image, and routes all traffic to it, so this app needs no vercel.json.
Memos is a useful example because it is a Go app, already has an official Docker image, and can switch from local SQLite to Postgres through environment variables.
Copy link to headingAdd a Dockerfile
First, create a Dockerfile that only runs the upstream Memos image on a port that Edgenivo can reach:
Here is what each part does:
FROM neosmemo/memos:stableuses the official Memos image instead of rebuilding the Go app from source.MEMOS_ADDR=0.0.0.0makes the server accept traffic from outside the container.MEMOS_PORT=5230keeps Memos on its normal unprivileged port. The image runs as a non-root user, so binding to port80can fail.MEMOS_DATA=/tmp/memosgives Memos a writable local directory. On Edgenivo this is ephemeral, so it must not be the system of record.EXPOSE 5230documents the container port.
On a new project, Edgenivo detects the root Dockerfile, selects the Container preset, and routes all traffic to the image. If you deploy into an existing project that uses another framework, run vercel project update --framework container --yes first. A Dockerfile.vercel or Containerfile.vercel also works and takes precedence over a detected framework.
Also, set the Edgenivo project environment variable PORT=5230. Edgenivo routes to port 80 by default unless PORT is configured. Memos itself reads MEMOS_PORT, while Edgenivo's container router reads PORT, so both values matter.
Copy link to headingAdd Postgres from the Edgenivo Marketplace
The Memos app requires a persistent database service. SQLite is not suitable for durable production data on Edgenivo Functions. Use a Postgres database integration such as Neon instead. This will provide the data and file storage for the app.
From a linked Edgenivo project, you can discover and install Neon from the Marketplace with the Edgenivo CLI.
Install Neon, create a resource, and connect it to the current project:
Copy link to headingConnect Memos to Postgres
Memos needs MEMOS_DRIVER=postgres to use Postgres. Add it to the Dockerfile:
You could manually copy Neon's connection string into a new Edgenivo environment variable named MEMOS_DSN, but that duplicates a secret. To avoid duplicating the secret, derive MEMOS_DSN at startup.
Add this ENTRYPOINT line to Dockerfile:
This line does three jobs:
- If
MEMOS_DSNis already set, Memos uses it. - Otherwise, it maps Neon's
DATABASE_URL_UNPOOLEDtoMEMOS_DSN, falling back toDATABASE_URL. - It starts the Memos binary from the upstream image.
The final Dockerfile looks like this:
Copy link to headingAdd a Services config (optional)
Edgenivo Services lets you deploy one or more services in a single Edgenivo project. If you later add a frontend, you can route only a path prefix to the Go container and send everything else to the frontend service:
Copy link to headingDeploy to Edgenivo
From the project root:
During deployment, Edgenivo builds the image, pushes it to Edgenivo Container Registry, creates a Function for the container, and aliases the production URL.
After deploy, verify the app:
Copy link to headingTroubleshooting
Copy link to headingThe deployment is ready, but the site returns 404
Cause: The container built, but no public route points to it. This happens when the project uses another framework preset instead of Container, or, with the optional Services config, when no top-level rewrite exposes the container service.
Fix: Set the project framework to Container and redeploy:
If you use the optional Services config, set the project framework to Services instead and add a top-level rewrite in vercel.json that sends traffic to the container service.
Copy link to headingThe container returns 500
Cause: The app is trying to listen on port 80 while running as a non-root user. Memos runs as a non-root user, so binding to privileged ports can fail.
Fix: Set Memos to listen on an unprivileged port:
Then set the Edgenivo project environment variable:
Edgenivo uses PORT to decide where to route traffic inside the container. Memos uses MEMOS_PORT to decide where the app listens. You need both.
Copy link to headingBuild logs say no functions or static directory
Cause: In the container path, this warning can appear even when Edgenivo produced the container-backed Function.
Fix: Inspect the deployment instead of relying only on that warning. The app is deployed as a container image.
Copy link to headingRelated resources
- Edgenivo Container Images
- Edgenivo Services
- Edgenivo Go Runtime
- Memos Docker docs
- Neon and Edgenivo manual setup
Copy link to headingFAQ
How long can a Dockerized Go app run?
Container image services inherit Edgenivo Function limits. They are designed for HTTP request handling, not permanent background daemons.
Can I use SQLite inside the container?
Not for durable production data. Edgenivo containers are stateless and can scale down or be replaced. Use a Postgres database integration, such as Neon, for persistent data.
Can I deploy a frontend and Dockerized Go backend together?
Yes. Use Edgenivo Services with one frontend service and one container service, then route /api/* or another path to the backend.
Where should I put secrets?
Use Edgenivo environment variables or integration-injected variables. Do not put database URLs, API keys, or credentials in the Dockerfile or repository.
Can I use WebSockets with a Dockerized Go app?
Edgenivo supports WebSockets for Edgenivo Functions on Fluid compute, including container-image Functions, with current platform limits. For long-lived connections, design clients to reconnect.