Skip to content

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

  1. You push a repo with a Dockerfile (or run dock deploy).
  2. The platform runs docker build against it.
  3. The image runs with resource limits, health checks and logs.
  4. 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:

dockerfile
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:

go
port := os.Getenv("PORT")
if port == "" {
    port = "8080"
}
log.Fatal(http.ListenAndServe(":"+port, mux)) // ":" = all interfaces

EXPOSE 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 .dockerignore for .git, node_modules, local builds and .env files.
  • Pin base image versions (node:22-alpine, not node: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

bash
curl -fsSL https://cli.dockhosting.dev/install.sh | sh   # Windows: irm https://cli.dockhosting.dev/install.ps1 | iex
dock login
dock deploy

Or 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:

EngineVariable
PostgreSQL / MySQL / MariaDBDATABASE_URL
MongoDBMONGODB_URI
RedisREDIS_URL
ClickHouseCLICKHOUSE_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 frontend
  • worker: 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.

Summarize with

Share

All posts

Create an account, run dock deploy, and get a live HTTPS URL in minutes.