# Deploy a Go Application with Docker Compose on xCloud

> Deploy a Go web service or API from Git on an xCloud Docker + Nginx server using Docker Compose or a Dockerfile, with the right port, environment variables and domain.

## What this guide covers

This guide shows you how to deploy a containerized Go application from Git on xCloud. You will select a Docker + Nginx server, connect a public or private repository, choose Docker Compose or Dockerfile deployment, map the application's listening port, configure environment variables, and launch the site on a staging or custom domain.

This workflow is useful for Go web services and APIs that can run as a long-lived container process.

## Prerequisites

Before you begin, prepare the following:
- An xCloud account with permission to add a site.
- An existing xCloud server that uses the **Docker + Nginx** stack, or permission to create one.
- A Git repository containing your Go application.
- Either a `docker-compose.yml` file or a `Dockerfile` in the repository.
- The internal port on which the Go application listens.
- Any runtime environment variables required by the application.
- A custom domain, if you do not want to use an xCloud staging domain.

For a private repository, [connect a Git provider](/docs/how-to-integrate-a-git-provider-with-xcloud/) or be ready to add an xCloud-generated SSH deploy key to the repository.

> **Security:** Do not commit production credentials, API keys, database passwords, or private keys to the repository. Add sensitive values through the environment configuration in xCloud.

## Prepare the Go application

Your Go process must listen on all container interfaces, not only on `localhost`. A typical application reads its port from an environment variable and starts the HTTP server on `0.0.0.0:<port>` or `:<port>`.

For example:

```go
port := os.Getenv("PORT")
if port == "" {
    port = "8080"
}
log.Fatal(http.ListenAndServe(":"+port, handler))
```

### Example Dockerfile

A multi-stage Dockerfile keeps the runtime image smaller by compiling the binary separately from the final container:

```dockerfile
FROM golang:1.24-alpine AS build
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /out/app ./cmd/server

FROM alpine:3.21
RUN apk add --no-cache ca-certificates
COPY --from=build /out/app /usr/local/bin/app
EXPOSE 8080
ENV PORT=8080
CMD ["/usr/local/bin/app"]
```

Adjust the Go version, build package, and port to match your project.

### Example Docker Compose file

```yaml
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    restart: unless-stopped
    environment:
      PORT: "8080"
    ports:
      - "8080:8080"
```

The container port must match the port configured in xCloud. If your Compose file contains multiple services or exposed ports, select the service port that should receive public traffic.

## Step 1: Start a Git deployment

From the xCloud dashboard, select **New Site**. Choose **Deploy via Git** as the deployment method.

![Choosing Deploy via Git for a new site in the xCloud dashboard](/_landing/docs/deploy-docker-compose-from-git-01-deploy-via-git.png)

**Expected result:** xCloud opens the server-selection step for the new Git deployment.

## Step 2: Select a Docker + Nginx server

Choose an existing server that uses the **Docker + Nginx** stack, then select **Continue**.

![Selecting a Docker + Nginx server for the Git deployment](/_landing/docs/deploy-docker-compose-from-git-02-select-docker-nginx-server.png)

If no compatible server is available, create one before continuing — see [how to deploy a custom Docker application from a Git repository](/docs/how-to-deploy-custom-docker-application-from-git-repository/) for the server creation steps.

**Expected result:** xCloud opens the **Deploy Any App From Git** configuration screen.

## Step 3: Select the repository and branch

Choose one of the supported repository-access methods:

| Repository type | How to connect it |
|---|---|
| Public repository | Search for the repository or paste its HTTPS URL. |
| Connected GitHub repository | Select the connected account, repository, and branch. |
| Private SSH repository | Use the SSH option, add the generated deploy key to the repository, then verify access. |

Confirm the branch xCloud will deploy. xCloud can prefill the repository's default branch, but you should review it before continuing.

**Expected result:** xCloud analyzes the repository and displays the container deployment settings.

## Step 4: Choose Docker Compose or Dockerfile mode

Select **docker-compose.yml** when the repository defines the application with Docker Compose. Enter the repository-relative path to the Compose file, such as `docker-compose.yml` or `deploy/docker-compose.yml`, then select **Re-Scan**.

![Docker Compose mode with the compose file path and Re-Scan button](/_landing/docs/deploy-docker-compose-from-git-03-compose-mode.png)

Select **Dockerfile** when xCloud should build one application image directly from a Dockerfile. Enter its repository-relative path, such as `Dockerfile` or `docker/Dockerfile`.

![Dockerfile mode with the Dockerfile path field](/_landing/docs/deploy-docker-compose-from-git-04-dockerfile-mode.png)

| Option | Use it when | Required setting |
|---|---|---|
| `docker-compose.yml` | The application uses one or more Compose services. | Compose-file path and the primary service port. |
| `Dockerfile` | The repository builds a single app container. | Dockerfile path and container port. |

**Expected result:** xCloud scans the selected file and enables the relevant port and deployment fields.

## Step 5: Configure the public application port

Enter or select the port on which the Go application listens inside the container. In the examples above, this is `8080`.

The values must agree across the application, container configuration, and xCloud:
- Go's HTTP listener uses `8080`.
- The Dockerfile exposes `8080`.
- Docker Compose maps `8080:8080`.
- xCloud uses `8080` as the primary or container port.

If the Compose file exposes several ports, choose the port that serves the HTTP application. Database, cache, and internal worker ports should not be selected as the public site port.

**Expected result:** xCloud knows which container port to route through Nginx.

## Step 6: Choose a staging or custom domain

Use the generated xCloud staging domain when you want to validate the deployment before changing DNS. Select **Use a live domain instead** when you are ready to connect a custom domain.

For a custom domain, enter the hostname and complete the DNS verification shown by xCloud. SSL configuration follows the domain setup in the deployment flow.

**Expected result:** The deployment has a public hostname that xCloud can route to the Go container.

## Step 7: Add environment variables and review the deploy script

Expand **Environment & deploy script**.

![The Environment & deploy script section with the .env option](/_landing/docs/deploy-docker-compose-from-git-05-environment-deploy-script.png)

Enable **Provide a .env file** when the application requires runtime settings. Add only the values needed by the deployed environment, for example:

```dotenv
PORT=8080
APP_ENV=production
LOG_LEVEL=info
```

Review the deployment script before launching the site. For Compose deployments, xCloud provides a Compose-based script that stops the current stack and starts a rebuilt stack using the selected Compose file. Modify it only when your repository requires additional verified commands.

**Expected result:** The deployment has the required runtime configuration and an appropriate container start procedure.

## Step 8: Deploy and verify the Go application

Review the repository, branch, file path, port, domain, environment, and deploy script. Select **Deploy**.

After deployment completes:
1. Open the site's public URL.
2. Confirm the expected page or API response loads.
3. Open the site logs in xCloud and check that the Go process started without errors.
4. Confirm the application is listening on the same internal port configured in xCloud.
5. Exercise a lightweight health endpoint, such as `/health`, if the application provides one.

**Expected result:** The Go service is reachable through the xCloud domain and its container remains running.

## Update or redeploy the application

Push the application changes to the deployed branch, then redeploy the site from the xCloud dashboard. Connected-provider repositories can use auto-deploy on push when webhook deployment is enabled and the connected account has the required repository permission.

Before redeploying a production service, review schema migrations and other stateful operations. Keep destructive commands out of the default deploy script unless they are intentional and recoverable.

## Options and settings

| Setting | Purpose | Go guidance |
|---|---|---|
| Branch | Selects the Git revision to deploy. | Confirm the branch contains the Docker files and application code. |
| Compose/Dockerfile path | Identifies the container definition. | Use a repository-relative path. |
| Container or primary port | Tells Nginx where to send HTTP traffic. | Match the Go listener and container configuration. |
| Staging domain | Provides a temporary public URL. | Use it for initial verification. |
| Custom domain | Connects the production hostname. | Complete DNS verification before go-live. |
| Environment file | Supplies runtime configuration. | Set values such as `PORT`, database URLs, and feature flags without committing secrets. |
| Deploy script | Controls how containers are rebuilt and started. | Keep it deterministic and non-interactive. |
| Auto-deploy webhook | Deploys new commits automatically. | Available for connected providers when permission allows webhook creation. |

## Limits and edge cases
- The target server must use the Docker + Nginx stack.
- A Go server bound only to `127.0.0.1` inside the container will not accept proxied traffic. Bind it to all interfaces.
- A mismatch between the Go listener, Docker port, Compose mapping, and xCloud port causes gateway or connection errors.
- A Dockerfile path or Compose path is relative to the repository root and is case-sensitive on Linux.
- Private repositories require a connected provider or a verified SSH deploy key.
- Compose deployments with no running containers, no detectable ports, or a failed image build will not produce a reachable site.
- Additional Compose services such as PostgreSQL or Redis need persistent volumes and environment variables appropriate to the application. Do not expose their internal ports publicly unless the architecture requires it.
- Persistent application data should live in a named volume or external managed service, not only in the container filesystem. See [how to back up and restore Docker apps](/docs/backup-and-restore-docker-apps/).

## Troubleshooting

| Symptom | Likely cause | What to check |
|---|---|---|
| Build fails during `go mod download` | Missing module files, inaccessible private dependency, or incompatible Go version. | Confirm `go.mod`,`go.sum`, build credentials, and the Docker image version. |
| Deployment succeeds but the site returns a gateway error | The process is not listening, is bound to localhost, or uses the wrong port. | Check container logs and make the listener, Docker, Compose, and xCloud ports identical. |
| Container exits immediately | The binary path or `CMD` is incorrect, or a required variable is missing. | Review the image entrypoint, runtime logs, and environment settings. |
| Rebuild does not include recent code | The wrong branch or repository path was selected. | Verify the deployed branch, commit, Dockerfile path, and build context. |
| Database data disappears after recreation | The database or application data was stored only in the container layer. | Use a named volume or external database and verify the Compose volume mapping. |

## Frequently asked questions

### Does xCloud need Go installed directly on the server?

No. In this workflow, the Go toolchain and runtime are defined by the Docker image. The Docker + Nginx server builds or runs the container and routes web traffic to it.

### Can I deploy a Go API without a frontend?

Yes. Configure the API's HTTP port as the public container port. The public xCloud or custom domain then routes requests to the API.

### Should I choose Docker Compose or Dockerfile?

Use Dockerfile mode for a single container with straightforward runtime requirements. Use Docker Compose when the repository already defines multiple services, volumes, networks, or service-specific environment settings.

### Can I deploy from a private repository?

Yes. Use a connected GitHub account or the SSH flow with the generated deploy key, then verify repository access before deployment.

## Next steps

After the initial deployment, connect the production domain, enable auto-deploy if it fits your release process, and add application-level health checks and structured logging. For a multi-service Go application, review volume persistence and keep database or cache ports internal to the Compose network.

If you run into any issues deploying your Go application, feel free to reach out to our [support team](/docs/access-built-in-support-portal-in-xcloud/) for help.
