Built from your Dockerfile

Docker hosting in India: deploy any Dockerfile

Commit a Dockerfile at the root of your repository and we build the image from it and run it as your app. Go, Rust, Java, Ruby, Deno or a language we have no buildpack for: if it fits in one container, it gets HTTPS, custom domains, environment variables, logs and a managed PostgreSQL database.

From ₹100/month + 18% GST, PostgreSQL included, billed in INR.

Deploy Docker in 5 steps

  1. Commit a Dockerfile and connect the repository

    Place the Dockerfile in the repository root, not in a subfolder, and add a .dockerignore that leaves out .git, local dependencies and build output. Create an app, connect GitHub and pick the branch, or upload the same folder as a tar.gz with a deploy token.

  2. The Dockerfile builder is selected

    A Dockerfile at the root means the app is built from your image recipe instead of a buildpack, even if the repository also has a package.json or requirements.txt. Multi-stage builds work, and only the final stage ends up running.

  3. Listen on port 5000

    Every app is routed to port 5000 inside its container, whatever EXPOSE says. Make the server bind to 0.0.0.0 on the port in PORT with 5000 as the fallback, so the same image also runs on your laptop.

  4. Pass configuration and DATABASE_URL at runtime

    Keep secrets out of the Dockerfile. Set them as environment variables in the dashboard and read them when the process starts; when you attach PostgreSQL 16, its connection string reaches the container the same way, as DATABASE_URL.

  5. Connect your domain, no certificates in the image

    Add your domain, publish the TXT record to verify it, then point an A record or CNAME at the app. HTTPS is terminated in front of your container, so the image serves plain HTTP on port 5000 and never needs a certificate or port 443.

A minimal Docker app that deploys

Dockerfile
FROM golang:1.23-alpine AS build
WORKDIR /src
COPY go.mod ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /out/server .

FROM alpine:3.20
COPY --from=build /out/server /usr/local/bin/server
ENV PORT=5000
EXPOSE 5000
CMD ["server"]
main.go
package main

import (
	"fmt"
	"net/http"
	"os"
)

func main() {
	port := os.Getenv("PORT")
	if port == "" {
		port = "5000"
	}
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, "ok")
	})
	http.ListenAndServe("0.0.0.0:"+port, nil)
}
go.mod
module example.com/server

go 1.23

Docker gotchas to know before you push

  • No docker-compose: one image per app

    A docker-compose.yml in the repository is ignored. Run the database as the managed PostgreSQL attached to the app instead of a postgres service, and run a second service as a second app on your plan.

  • EXPOSE does not choose the port

    The router always sends traffic to port 5000. A container listening on 80 or 8080 builds, starts and reports running, then answers every request with a 502.

  • Persistent files go in /app/data

    Each app has a volume mounted at /app/data, whatever your WORKDIR is; everything else in the container filesystem is reset on each deploy. The volume is owned by uid 32767, so an image that switches to a non-root USER must run as that uid to write there.

  • Order layers for fast rebuilds

    Copy the dependency manifest and install dependencies before COPY . . so an ordinary code change reuses the cached dependency layer. Pin base image tags, such as alpine:3.20, rather than latest, so a rebuild does not change your runtime by surprise.

FAQ

Docker hosting questions

Not as a single app. Each app is built from one Dockerfile. Split the stack: the web service becomes this app, the database becomes the PostgreSQL included in your plan, and any other long-running service becomes another app; plans include one, three or six apps.
We build from the Dockerfile in your repository rather than pulling a finished image, but that Dockerfile can be one line, FROM followed by your public image and tag. Images in a private registry cannot be pulled during the build.
Port 5000, on 0.0.0.0. The platform routes every app to that container port and sets PORT to match for buildpack apps, so reading PORT with 5000 as the default works on the platform and on your machine.
Use the buildpack unless you need something it cannot give you, such as a system library or a custom runtime. With a buildpack there is no base image to keep patched; with a Dockerfile, updating the base image is your job.
Prefer an app? Add this site to your home screen.Get the app
Docker Hosting India – Container PaaS from ₹100/mo | Domain India