# Docker Service Zerops provides Docker support through dedicated Virtual Machine (VM) environments, ensuring maximum compatibility and isolation while maintaining integration with the broader Zerops ecosystem. This guide explains how to effectively use Docker services in Zerops, including best practices and important considerations. ## Why VMs While Zerops primarily uses native Linux containers for optimal performance, this VM-based approach allows you to run virtually any Docker container while maintaining Zerops' robust infrastructure management. You can learn more about [differences](/features/container-vs-vm) between Containers and Virtual Machines in Zerops. Before using Docker services, consider these important aspects: ### Virtual Machine Environment Docker services in Zerops operate in a full VM environment, which has several implications: - **Slower Boot Times**: VMs require more time to initialize due to full kernel boot - **Higher Resource Usage**: VMs include additional system overhead compared to native containers - **Scaling Limitations**: - Vertical scaling requires VM restart - Resources must be set as fixed values (no min-max ranges) - Zerops automatically restarts the VM when resource values are changed in UI - **Storage Management**: Disk space can only be increased, not decreased without recreation - **Build Phase Limitations**: Build phase runs in containers, not in the VM environment ### Advantages Despite these limitations, Docker services offer some benefits: - **Broad Compatibility**: Run almost any Docker container with minimal modification - **Familiar Environment**: Standard Docker runtime environment ## Configuration Guide ### Supported Version Currently supported Docker versions: ### Basic Structure Docker services in Zerops are configured through the `zerops.yaml` file. Here's a typical configuration pattern: ```yaml title="zerops.yaml" zerops: - setup: app run: prepareCommands: - docker image pull : # Always use specific version tags start: docker run --network=host : ports: - port: httpSupport: true ``` :::important Always use specific version tags (like `1.0.0`) instead of `:latest`. Zerops caches the `prepareCommands` output, which means a new `:latest` image won't be automatically pulled on subsequent deployments unless the cache is manually cleared or the commands change. ::: Refer to the [Docker recipe repository](https://github.com/zeropsio/recipe-docker) for an example configuration. :::note We are actively working on improving the speed of image caching after `run.prepareCommands` and reducing the startup time of runtime VMs. These improvements will be released in future updates. ::: ### Network Configuration Docker services require the `--network=host` flag for proper integration with Zerops: - **Direct Port Management**: Ports are managed through `zerops.yaml` - **Simplified Configuration**: Avoids double port exposure in Docker and Zerops - **Native Performance**: Direct access to host networking ### Docker Compose Support For projects using Docker Compose, additional configuration is required: 1. **File Deployment**: ```yaml title="zerops.yaml" build: deployFiles: ./docker-compose.yaml addToRunPrepare: ./docker-compose.yaml ``` 2. **Network Mode**: ```yaml title="docker-compose.yaml" services: your-service: image: your-image:1.0.0 network_mode: host ``` 3. **Start Command**: ```yaml title="zerops.yaml" run: start: docker compose up --force-recreate ``` ### Environment Variables When using Docker services, there's an additional layer to consider since environment variables defined in Zerops must be explicitly passed to your Docker containers. #### 1. Defining Variables in Zerops Define your environment variables in the `run.envVariables` section of your `zerops.yaml` (example uses [referenced](/features/env-variables#referencing-variables) variables): ```yaml title="zerops.yaml" zerops: - setup: app run: envVariables: DB_HOST: DB_PORT: ``` #### 2. Passing Variables to Docker Containers For single containers, pass variables using the `-e` flag: ```yaml title="zerops.yaml" run: prepareCommands: - docker image pull my-application:1.0.0 # Use specific version tags, not :latest start: docker run -e DB_HOST -e DB_PORT --network=host my-application:1.0.0 ``` :::important Always use specific version tags (like `1.0.0`) instead of `:latest`. Zerops caches the `prepareCommands` output, which means a new `:latest` image won't be automatically pulled on subsequent deployments unless the cache is manually cleared or the commands change. ::: For Docker Compose setups, pass environment variables in your `docker-compose.yaml`: ```yaml title="docker-compose.yaml" services: api: image: my-application:1.0.0 network_mode: host environment: - DB_HOST - DB_PORT ``` ## Implementation Examples ### Single Container ```yaml title="zerops.yaml" zerops: - setup: app run: prepareCommands: - docker image pull crccheck/hello-world:1.0.0 # Always use specific version tags start: docker run --network=host crccheck/hello-world:1.0.0 ports: - port: 8000 httpSupport: true ``` :::important Always use specific version tags (like `1.0.0`) instead of `:latest`. Zerops caches the `prepareCommands` output, which means a new `:latest` image won't be automatically pulled on subsequent deployments unless the cache is manually cleared or the commands change. ::: ### Single Service with Docker Compose ```yaml title="zerops.yaml" zerops: - setup: api build: deployFiles: ./docker-compose.yaml addToRunPrepare: ./docker-compose.yaml run: prepareCommands: - docker compose pull api start: docker compose up api --force-recreate ports: - port: 8000 httpSupport: true ``` ```yaml title="docker-compose.yaml (excerpt)" services: api: image: your-image:1.0.0 network_mode: host # other configuration... ``` ### Multiple Services with Docker Compose ```yaml title="zerops.yaml" zerops: - setup: apps build: deployFiles: ./docker-compose.yaml addToRunPrepare: ./docker-compose.yaml run: prepareCommands: - docker compose pull start: docker compose up --force-recreate ports: - port: 8000 httpSupport: true ``` ```yaml title="docker-compose.yaml (excerpt)" services: web: image: web-image:1.0.0 network_mode: host # other configuration... api: image: api-image:1.0.0 network_mode: host # other configuration... ``` ## Best Practices #### Image Management - **Always use specific version tags** instead of `:latest` - This prevents caching issues as Zerops caches `prepareCommands` output #### Resource Planning - Account for VM overhead in resource allocation - Plan for longer initialization times - Consider the impact on scaling operations #### Migration Consideration - Evaluate if your workload could run on native containers - Consider gradual migration for complex applications - Balance development effort against operational benefits ## Limitations and Workarounds ### Build Phase Since the build phase runs in containers rather than VMs: - Use `run.prepareCommands` for Docker-specific build steps - Consider external CI/CD for complex Docker builds - Leverage pre-built images when possible ### Scaling Operations Docker services in Zerops have specific scaling characteristics that differ from native containers: #### Vertical Scaling - Resources must be defined with **fixed** values instead of min-max ranges - CPU, RAM, and disk are specified as single values: ```yaml verticalAutoscaling: cpu: 3 ram: 2 disk: 20 ``` - Any change to these values through the UI triggers an automatic VM restart - Plan your resource allocation carefully to minimize scaling operations #### Horizontal Scaling - Still supports multiple containers through `minContainers` and `maxContainers` - Consider breaking large services into smaller components - Implement proper health checks for reliable scaling - Use horizontal scaling when possible to avoid VM restarts