How to Deploy a Docker Container to the Cloud (Without Managing a Server)
Turn any Dockerfile into a live HTTPS app: production Dockerfiles, multi-stage builds, PORT and health checks, and managed databases on a private network.
- Published
- Reading time
- 4 min
On this page
Key takeaways
- Any app with a Dockerfile can be deployed: the platform runs docker build on your repo and runs the image with HTTPS in front.
- Your container must listen on 0.0.0.0 and the PORT variable; use multi-stage builds to keep the image small.
- Run one service per container, and use managed databases instead of a database server inside your image.
Running Docker on a VPS means installing the daemon, patching the OS, setting up a reverse proxy, renewing certificates and restarting things when they fall over. A container platform keeps the useful part (your image runs the same everywhere) and handles everything else.
How it works
- You push a repo with a
Dockerfile(or rundock deploy). - The platform runs
docker buildagainst it. - The image runs with resource limits, health checks and logs.
- A TLS endpoint puts it on
https://<project>.dockhosting.cloud.
You keep full image compatibility without the daemon or orchestration work.
1. A production Dockerfile
Here's a Go API, a good example of a multi-stage build:
FROM golang:1.23-alpine AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /app ./cmd/server
FROM gcr.io/distroless/static
COPY --from=build /app /app
USER nonroot
ENTRYPOINT ["/app"]The final image contains only the binary: no shell, no package manager and a much smaller attack surface. The same pattern works for Node.js, Python, Java and Rust. Build in one stage, run from a slim one.
2. Listen on PORT, on 0.0.0.0
The platform tells your container which port to use through the PORT environment variable, and connects from outside the container:
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
log.Fatal(http.ListenAndServe(":"+port, mux)) // ":" = all interfacesEXPOSE in the Dockerfile is documentation only. What matters is the address your process binds to. Most first-deploy failures come from this, so see 502 Bad Gateway: 8 causes.
3. Keep images small and builds fast
- Order layers by how often they change: dependency manifests first, then
RUN install, then the source code. Rebuilds then reuse the cached layers. - Add a
.dockerignorefor.git,node_modules, local builds and.envfiles. - Pin base image versions (
node:22-alpine, notnode:latest) for reproducible builds. - Pass build-time values with
ARG. Build args are supported.
DockHosting keeps the build cache warm on every app server, so rebuilds reuse more layers.
4. Deploy
curl -fsSL https://cli.dockhosting.dev/install.sh | sh # Windows: irm https://cli.dockhosting.dev/install.ps1 | iex
dock login
dock deployOr connect a GitHub repository to deploy on every push. Each deploy switches traffic with zero downtime, and the previous image is kept for rollbacks.
5. Databases: managed, not in the image
Don't run Postgres in your container. When the container is replaced, its data goes with it. Attach a managed database instead:
| Engine | Variable |
|---|---|
| PostgreSQL / MySQL / MariaDB | DATABASE_URL |
| MongoDB | MONGODB_URI |
| Redis | REDIS_URL |
| ClickHouse | CLICKHOUSE_URL |
They're reachable over a private network through an internal hostname, with no public port, and paid plans get daily backups.
For files that must survive restarts (uploads, SQLite for small tools), paid plans include persistent storage: 1 GB on Hobby, 5 GB on Pro and 20 GB on Team.
6. Multi-service apps
One project runs one containerized service. Split a Compose file into projects:
web: your API or frontendworker: a queue consumer (same image, different start command)- Managed Redis as the queue between them, and managed PostgreSQL for data
They talk over the private network, just like Compose services do.
What's not allowed (and why)
Images that run a database server or a remote desktop (VNC, Openbox and similar) are refused at build time. Databases belong in managed databases, which are backed up and sized separately from your app's memory.
New to platforms like this? Read what a PaaS is. Deploying Next.js? Follow the Next.js Docker guide.
Frequently asked questions
Can I use docker-compose?
Each project runs one containerized service. A Compose setup deploys as separate projects (for example web and worker) that talk over the private network, with managed databases replacing the database containers.
Can I run PostgreSQL or MySQL inside my Docker image?
No. Dockerfiles that run a database server are refused at build time. Use a managed database instead: it's linked to your app, backed up on paid plans and doesn't take your app's memory.
Can I use images from a private registry?
Yes. Base images from private registries are supported, along with multi-stage builds and build args.
How much memory can a container use?
512 MB on Free (shared with its database), 1 GB on Hobby, up to 2 GB per app on Pro and up to 4 GB per app on Team.
- Docker
- Containers
- Deployment
- Tutorial
Written by Doughmi ILYAS
Doughmi builds DockHosting, the developer-first platform behind dock deploy: the build system, the managed databases and the dashboard. On this blog: guides to shipping apps without running servers, written with the commands the platform actually ships.
