One-Click Docker Deployment: From Blank Server to Running App
"One-click deploy" sounds like marketing until you have done the manual version. Then it sounds like a description of a very long list of things you no longer have to do.
This article breaks down what actually happens between "I want to run Immich" and "Immich is live at a real URL with a valid certificate" — and why doing it by hand is where most homelab evenings go.
The nine things that happen when you deploy a container
A container is the easy part. Everything around it is the work:
- Pick the image and pin it.
:latestis convenient and occasionally a surprise. A platform should know the image it is going to pull. - Decide the persistent paths. Which directories must survive a container rebuild? Get this wrong and your photo library lives inside a container that disappears on the next update.
- Map ports. Host port 8080 is taken. Again.
- Set environment variables and secrets. Database passwords, admin users, API tokens, claim tokens.
- Create or attach a network. So the container can talk to its database and nothing else it should not.
- Write a reverse-proxy entry. Caddy or Nginx config that routes
app.example.comto the right container port. - Create the DNS record. The subdomain has to resolve, and it has to resolve to the right host.
- Issue and install a TLS certificate. Then renew it forever.
- Wait for a health check. "Started" is not "working." The container can be running and still return 500s.
You can do all nine by hand. People do. It is also the reason so many homelabs have a service that has been "almost done" since March.
What "one-click" should mean
A deployment button that only covers step 1 is not one-click; it is docker run with a nicer font. Genuine one-click deployment covers the whole list, in order, with a real result at the end: a URL that opens, over HTTPS, with a green health check.
DashCaddy's deploy path does exactly that. You pick a template from the app catalog, fill in the few values that are genuinely yours (a subdomain, maybe a media path or a claim token), and press Deploy. DashCaddy then:
- pulls the pinned image;
- creates the persistent volumes;
- attaches the container to its network;
- writes the reverse-proxy route;
- creates the DNS record;
- issues the certificate;
- and polls the app's health endpoint before reporting success.
If the health check does not pass, you get a failure — not a container that is technically running and practically broken.
The same deploy, two ways
Every template is available through the dashboard and through the REST API. The API path is what makes automation possible. A deploy is a single authenticated POST whose body names the app and the handful of settings that matter:
curl -X POST https://your-host/api/v1/apps/deploy \
-H "X-API-Key: <your key>" \
-H "Content-Type: application/json" \
-d '{
"appId": "immich",
"config": { "subdomain": "photos" }
}'
Because the endpoint is a normal REST route, the same call works from a shell script, a CI job, or an AI assistant connected over the MCP server. The install guides in the catalog document the exact payload for each app — see the Plex guide or the Jellyfin guide for the pattern.
Where manual deployment still makes sense
Automation is not a religion. Reach for the manual path when:
- you are evaluating a new app and want to poke at it without a permanent footprint;
- the image needs a custom build or a patch the template does not cover;
- you are debugging and need to run the container with different flags than the template uses.
That is also why a platform should let you attach to an existing container rather than forcing every service to be born inside it. DashCaddy supports adopting an already-running container so existing work is not thrown away.
A deployment checklist that fits on a napkin
Whatever tool you use, verify these five things after the first deploy:
- The URL opens over HTTPS with a valid, non-self-signed certificate.
- The data path is a host directory you recognize — check with
docker inspectif unsure. - The DNS record is yours and points where you think it does.
- The health check is green, not merely "running."
- A restart brings it back.
rebootthe host and confirm the service returns without you.
If all five hold, you have done real one-click deployment, regardless of which tool did it.
Getting started
Install DashCaddy on any Linux host:
curl -fsSL https://get.dashcaddy.net | bash
Then open the dashboard, browse the catalog, and deploy something. The installation docs cover host requirements, and First Service walks through the very first deploy in detail.
Once the first app is up, the natural next questions are how to access it remotely and how to know when it goes down.