# Publish your first app on Gyro Containers: Docker image, port, health check and replicas

https://www.gyrohosting.com/en/knowledgebase/article/gyro-containers-publish-first-app

- **What you will learn**: How to publish your own Docker image on Gyro Containers, what to check so the image works with the platform, the health check and replica count, and pulling from a private registry.
- **Time**: 12 minutes
- **Who this is for**: Developers with a Docker image ready.
- **What you need**: An active Gyro Containers environment and a Docker image that is public or for which you have credentials.

## 1. Is your image platform-friendly?

| Rule | Why / what to do |
| --- | --- |
| **Non-root user** | Containers run as user `10001`. Define `USER 10001` (or another unprivileged user) and set file permissions accordingly. |
| **Port 1024 or higher** | An unprivileged user cannot listen on 80/443; use a port such as `8080`. |
| **Version tag** | Use a fixed tag like `1.4.2` instead of `latest`; it is needed for rollback and repeatable releases. |
| **Logs to standard output** | Write application logs to `stdout`/`stderr`; the Logs page shows them. |
| **No persistent disk** | Files written are deleted when the container restarts (`/tmp` is temporary, 512 MiB). Write persistent data to [Object Storage](https://www.gyrohosting.com/en/knowledgebase/article/nesne-depolama-s3-rehberi) or a separate database. |
| **Architecture** | The image must be `linux/amd64`. |

> **Info**
> 
> For images whose main process needs root, the service stops with "Start-up configuration error" (CreateContainerConfigError). The fix: use a non-root image or define `USER`. An example of a ready-made unprivileged image: `nginxinc/nginx-unprivileged`.

## 2. Create a service in the panel

1. Open your environment from **My Services** and go to **Services**.
2. Press **New service**.
3. Fill in the form:

| Field | What to write |
| --- | --- |
| **Service name** | Lowercase letters, digits, `-`; starts with a letter, up to 40 characters (for example `api`). Address: name + your code. |
| **Image** | `user/app:1.4.2` for `docker.io`, `ghcr.io/company/app:1.4.2` for GitHub, `registry.ist.gyrohosting.com/<your-code>/app:1.4.2` for the Gyro registry. |
| **Port** | The port your application listens on (for example `8080`). Required if it will be reachable from outside. |
| **Replicas** | Number of running instances. 2 or more for resilience. |
| **CPU / replica, Memory / replica** | Resources per replica (default 0.25 vCPU / 256 MB). |
| **Health check path** | An HTTP path such as `/healthz`. If empty, a TCP connection to the port counts as healthy. |
| **Public (HTTPS address)** | If ticked the service gets the address `name-code.gyroapp.net`. If not, it is reachable only from inside the environment at `http://name`. |
| **Environment variables** | One `KEY=VALUE` per line. Add values like passwords as a [secret](https://www.gyrohosting.com/en/knowledgebase/article/gyro-containers-variables-and-secrets) instead. |
| **Command (optional)** | Arguments for the image's default command. |

1. Press **Create and start**. The status first shows **Deploying**, then **Running**.

> **Info**
> 
> The **health check** does two things: a new revision gets no traffic until its instance is ready (the basis of zero-downtime rollout), and if you give an HTTP path an instance that stops answering is restarted automatically. Define an HTTP health path when you can.

## 3. Pulling a private image

If your image is not public, define the registry credentials once:

1. On the **Node Pool** page open the **Private image registry** section.
2. Enter the **Registry address** (for example `ghcr.io`), **Username** and **Token / password**. The token should be **pull (read) only**.
3. Press **Save**. One private registry is defined per environment; the token is stored encrypted and never shown again.

To keep your own images in Gyro's registry see [Gyro image registry](https://www.gyrohosting.com/en/knowledgebase/article/gyro-containers-image-registry); there you do not need to define credentials separately.

## 4. From the command line

```
gyro container service create 12345 --name api \
  --image ghcr.io/company/app:1.4.2 --port 8080 \
  --replicas 2 --cpu-m 250 --memory-mi 256 \
  --health-path /healthz --public \
  --env '{"MODE":"prod"}'
```

To view and follow the service:

```
gyro container service list 12345
gyro container service get 12345 api
```

## 5. After publishing

- **Address:** Click the address in the service table. The first request may take a few seconds to be ready.
- **Status labels:** **Deploying**, **Running**, **Error**, **Waiting for capacity**, **Stopped**. If there is an error or waiting state, the cause and a suggested fix appear under the row ([Common errors](https://www.gyrohosting.com/en/knowledgebase/article/gyro-containers-common-errors)).
- **Logs:** Choose your service on the **Logs** page to see its output ([Logs and graphs](https://www.gyrohosting.com/en/knowledgebase/article/gyro-containers-logs-and-graphs)).
- **Updating:** for a new image version see [Scaling, updating and rollback](https://www.gyrohosting.com/en/knowledgebase/article/gyro-containers-scaling-updating-rollback).

## 6. Frequently asked questions

**Can I do the same as Docker Compose or docker run ?**

Each service is created separately. The equivalents of `docker run` options: port → **Port**, `-e` → **Environment variables**, `--restart` → the platform restarts it itself, `-v` (disk) is not supported.

**My image is bigger than 1 GB; is that a problem?**

Pulling takes longer. Making the image smaller (multi-stage builds, alpine/distroless) speeds up deploys.

**How do two services in the same environment connect?**

Through the internal address: `http://other-service` (port 80, which forwards to the target service's port). The target service does not need to be public.

**Can I rename a service later?**

No. Create a new service with the new name and delete the old one.

## Next step

- [Gyro image registry](https://www.gyrohosting.com/en/knowledgebase/article/gyro-containers-image-registry)
- [Variables and secrets](https://www.gyrohosting.com/en/knowledgebase/article/gyro-containers-variables-and-secrets)
