Docker Deployment
This guide explains how to deploy built container images to a Docker or Podman runtime. KIOPS's Docker deployment is driven by docker-compose, so a single service and a multi-container stack share the exact same deployment flow.
Why Read This Guide
By following this guide, you can deploy a service to a single server using docker-compose without a Kubernetes cluster, and secure a safety net through automatic pre-deployment backups. Non-developer operations team members only need to follow three steps — "Select image version → Choose connection method → Click Deploy" — and only use Compose edit mode when they need finer-grained settings.
Docker vs Kubernetes deployment comparison
- Complexity: Docker is simple, Kubernetes is more complex to configure.
- Scalability: Docker has limited scalability, Kubernetes has auto-scaling support.
- High Availability: Docker requires manual configuration, Kubernetes has built-in support.
- Recommended For: Docker is best for development, testing, and small-scale deployments. Kubernetes is recommended for staging and production.

Before You Start: Terms to Know
Before diving in, here is a one-line definition for each term that appears repeatedly. When a term first shows up in the body, you will see a "(See: Glossary)" pointer.
| Term | Definition |
|---|---|
| Container | An isolated environment that runs one application. |
| Image | A snapshot (template) used to create a container. |
| Docker Compose | A tool that bundles multiple container definitions into one YAML file and launches them together. |
| Volume | Persistent storage that survives container restarts. |
| Environment variable | A setting injected at runtime (e.g., DATABASE_URL). |
| Auto-backup | A KIOPS feature that snapshots the current container/volume state right before a deployment. |
Prerequisites
Before starting deployment, verify the following:
- Docker/Podman runtime registered: Docker or Podman runtime must be registered on the [Runtime Environment] page.
- Image build complete: The image to deploy must be pushed to the registry.
- docker-compose.yml defined: A service's deployment configuration is managed in docker-compose.yml. This applies equally to single-container and multi-container services.
Step 1: Go to Deploy Stage
- Navigate to the [Service Management] page.
- Select the service to deploy.
- Click the Deploy stage in the pipeline.
Step 2: Select Docker Deployment
- Select Docker as the deployment type.
- Select the target runtime.
- Docker: Docker Engine based runtime. Most common with wide compatibility.
- Podman: Rootless container runtime with enhanced security. Operates without a daemon.
- It is a container runtime compatible with Docker but operates without a daemon and supports rootless mode. Recommended for security-critical environments.
Step 3: Enter Deploy Options
The only input the Docker deploy modal requires is the Image Version. The actual UI label is Image Version; this guide uses "image tag/version" interchangeably for clarity. The "Auto-backup before deploy" row below is not an input — it describes behavior that runs automatically during deployment. (See: Image, Auto-backup)
| Item | Description |
|---|---|
| Image Version (input) | The container image tag (version) to deploy. Select from the list of images registered in the build history. (You cannot type in a version that is not in the list; run a build first.) |
| Auto-backup before deploy (automatic) | This is not a toggle you turn on or off. Right before deployment, KIOPS automatically backs up the current containers and volumes. The backup is written to a local directory (/var/backups/k8scontrol/...) on the target server. |
The pre-deploy auto-backup is written to a local directory (/var/backups/k8scontrol/...) on the target server; it is not uploaded to external storage (object storage, etc.) in [Backup Management]. It also does not block deployment — if the backup fails, deployment still continues and only a warning is logged. There is no user-facing on/off toggle.
Container name, ports, volumes, environment variables, and other detailed settings are not entered in the deploy dialog. The deploy dialog only exposes the image version input; all detailed configuration — container name, port mappings, volume mounts, environment variables, network settings — is handled in the docker-compose.yml edit mode (docker-compose.yml edit mode). See Editing docker-compose.yml for details.
Step 4: Run Deployment
- Review the image version.
- Click the Deploy button.
- In the Connection method modal, choose VPN or Direct SSH. Because deployment requires an SSH connection to the target server, this modal appears every time. If no VPN covers the target IP, this step is automatically skipped to Direct SSH.
- The backend runs
docker-compose pullfollowed bydocker-compose up -dto update the stack. - Deployment progress logs stream in real time. When the log finishes cleanly, confirm the container shows
Runningin Step 5: Check Container Status below. If you see an error in the log or the container fails to come up, check the Troubleshooting section at the bottom of this page and the Log Viewer tab of the operations modal to find the cause.
If a service is registered as multi-service, all services declared in docker-compose.yml are updated together in a single deployment. The flow is the same whether you deploy a single service or a multi-service stack.
Editing docker-compose.yml
Container name, port mappings, volumes, environment variables, networks, and every other detailed setting are managed in docker-compose.yml. Edit them directly in KIOPS's Compose edit mode. (See: Docker Compose, Volume, Environment variable)
Editable Items
services:
api:
image: harbor.company.com/library/app:latest
container_name: my-web-app
restart: unless-stopped
ports:
- "8080:80"
- "8443:443"
volumes:
- app-data:/app/data
- ./config:/app/config:ro
environment:
NODE_ENV: production
DATABASE_URL: ${DATABASE_URL}
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
app-data:
| Item | docker-compose key |
|---|---|
| Container name | container_name |
| Restart policy | restart (no / on-failure / always / unless-stopped) |
| Port mapping | ports |
| Volume mount | volumes |
| Environment variables | environment or env_file |
| Network settings | networks |
Do not put passwords or API keys directly in docker-compose.yml. Move them to an .env file or a Secret.
Step 5: Check Container Status
Check container status in the operations modal. The Docker operations modal contains the Overview / Container List / Log Viewer / Command Execution / Domain Settings tabs (the Log Viewer and Command Execution tabs appear only when you have the corresponding permission). Domain-targeted DAST scans have been moved to the [Security Analysis] page and are no longer in the operations modal.
- Click the Operations card for the service on the [Service Management] page.
- In the operations modal, select the Container List tab to see:
- Status: Running / Stopped / Error
- Ports: Mapped port information
- Created Time: When the container was created
- Resources: CPU / Memory usage
Container Controls
Use the Container List tab in the operations modal to restart, stop, or remove each container. The tab is shown only when you have permission. Redeploying the docker-compose stack is not done in the operations modal, but in the pipeline Deploy stage — the Docker deploy modal or Compose edit mode.
Troubleshooting
Container Startup Failure
- Port conflict: Change the host port in docker-compose.yml.
- Image not found: Verify the tag exists in the registry and credentials are correct.
- Permission issue: Check permissions on volume mount paths.
Container Crash (Repeated Restarts)
- Missing environment variables: Verify required environment variables are set.
- Dependency issue: Check error messages in logs.
- Insufficient memory: Adjust resource limits or optimize the application.
Cannot Access from Outside
- Port not mapped: Verify the
portsconfiguration in docker-compose.yml. - Firewall blocking: Allow the port in the host firewall.
- Internal container error: Check logs and application status.
Check real-time logs in the Log Viewer tab of the operations modal.
Common Pitfalls
- Using the latest tag: Using
latestfor the image version means each deploy pulls a different image, you lose a stable rollback target, and two nodes can end up with different images even at the same point in time. In production, use fixed tags that include a build ID or commit hash (e.g.,main-abc123,v1.2.3). - Compose YAML indentation: docker-compose.yml uses YAML syntax, so use 2 spaces for indentation, no tab key. Even a single misaligned space or a mixed-in tab causes the entire deployment to fail with errors like
yaml: line N: did not find expected key. KIOPS's Compose editor flags indentation errors in advance — check that there are no red underlines before saving.
What's Next
If the Docker deployment finished successfully, here is a recommended path:
- Check auto-backup: The pre-deploy auto-backup is written to a local directory (
/var/backups/k8scontrol/...) on the target server and does not block deployment if it fails. If you need durable retention, also configure a separate backup policy on the [Backup Management] page. - Learn the Compose edit guide: Detailed settings such as container name, ports, and volumes are configured in Compose edit mode. Walk through the most common options once so you can recognize them later.
- Use the operations modal: Get comfortable with the Log Viewer, Command Execution, and Container List tabs in the operations modal so you can inspect container state and respond quickly when issues happen.
Related Guides
- K8s Deployment - Kubernetes cluster deployment.
- Rollback - Restore to previous version.
- Operations Management - Container monitoring.