Перейти к основному содержимому

Docker Targets

Docker targets enable command execution within containerized environments. Xec provides comprehensive Docker integration with support for container lifecycle management, volume mounting, networking, and Docker Compose.

Basic Configuration

Define Docker containers in the targets.containers section:

targets:
containers:
app:
image: node:18
workdir: /app
volumes:
- ./src:/app

Container Properties

Essential Properties

targets:
containers:
basic:
# Container identification (one required)
image: ubuntu:22.04 # Docker image to use
container: existing-container # OR existing container name/ID

# Common settings
workdir: /workspace # Working directory
user: "1000:1000" # User ID or name

Advanced Properties

targets:
containers:
advanced:
image: node:18-alpine

# Volumes
volumes:
- ./src:/app:rw # Read-write mount
- ./config:/config:ro # Read-only mount
- data:/data # Named volume
- /tmp:/host-tmp # Absolute path

# Networking
ports:
- "3000:3000" # Host:Container
- "8080:80"
network: my-network # Network name

# Container settings
restart: unless-stopped # Restart policy
privileged: false # Privileged mode
tty: true # Allocate TTY
autoRemove: true # Remove after exit

# Resource limits
memory: 512m # Memory limit
cpus: "0.5" # CPU limit

# Health check
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 10s
retries: 3
startPeriod: 40s

Execution Modes

Run Mode (Default)

Creates new container for each command:

targets:
containers:
ephemeral:
image: alpine:latest
runMode: run # Default
autoRemove: true

# Each command creates new container
# xec in containers.ephemeral "echo test"

Exec Mode

Executes in existing container:

targets:
containers:
persistent:
container: my-app-container # Existing container
runMode: exec

# Commands run in existing container
# xec in containers.persistent "ps aux"

Hybrid Mode

targets:
containers:
smart:
image: postgres:15
container: db-container
# Automatically uses exec if container exists,
# otherwise creates with run

Volume Management

Volume Types

targets:
containers:
volumes-demo:
image: ubuntu:22.04
volumes:
# Bind mount (relative path)
- ./app:/app

# Bind mount (absolute path)
- /var/log:/logs:ro

# Named volume
- mydata:/data

# Anonymous volume
- /tmp

# With options
- type: bind
source: ./config
target: /config
readonly: true

Volume Permissions

targets:
containers:
permissions:
image: node:18
volumes:
- ./src:/app:rw # Read-write (default)
- ./config:/config:ro # Read-only
- ./cache:/cache:rw,z # With SELinux label

# Run as specific user
user: "1000:1000"

Networking

Port Mapping

targets:
containers:
web:
image: nginx:alpine
ports:
- "80:80" # HTTP
- "443:443" # HTTPS
- "127.0.0.1:8080:8080" # Bind to localhost only
- "3000-3005:3000-3005" # Port range

Network Modes

targets:
containers:
# Default bridge network
bridge:
image: alpine
network: bridge

# Custom network
custom:
image: alpine
network: my-app-network

# Host network
host:
image: alpine
network: host

# No network
isolated:
image: alpine
network: none

Container Linking

targets:
containers:
database:
image: postgres:15
network: app-network

app:
image: node:18
network: app-network
env:
DB_HOST: database # Can reference by name

Environment Variables

targets:
containers:
configured:
image: node:18
env:
# Simple values
NODE_ENV: production
PORT: "3000"

# From secrets
API_KEY: ${secrets.api_key}
DB_PASSWORD: ${secrets.db_password}

# Complex values
DATABASE_URL: "postgres://user:pass@db:5432/mydb"

# From host environment
HOME: ${env.HOME}
USER: ${env.USER}

Environment Files

targets:
containers:
from-file:
image: node:18
envFile:
- .env
- .env.production

Container Lifecycle

Restart Policies

targets:
containers:
# Always restart
critical:
image: redis:alpine
restart: always

# Restart on failure
resilient:
image: app:latest
restart: on-failure
restartMaxRetries: 5

# Don't restart
oneshot:
image: alpine
restart: "no"

Auto-removal

targets:
containers:
# Remove after execution
temporary:
image: alpine
autoRemove: true

# Keep container
persistent:
image: postgres:15
autoRemove: false

Health Checks

targets:
containers:
healthy:
image: nginx:alpine
healthcheck:
# Command-based check
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/"]

# Or shell command
# test: "curl -f http://localhost/ || exit 1"

# Timing configuration
interval: 30s # Check interval
timeout: 10s # Check timeout
retries: 3 # Failure retries
startPeriod: 40s # Grace period

Labels and Metadata

targets:
containers:
labeled:
image: app:latest
labels:
app: myapp
environment: production
version: "1.2.3"
"com.example.team": backend
"com.example.git-commit": ${env.GIT_COMMIT}

Docker Compose Integration

targets:
# Global compose configuration
$compose:
file: docker-compose.yml
project: myproject

containers:
# Reference compose service
web:
$service: web

# Override compose settings
db:
$service: database
env:
POSTGRES_PASSWORD: ${secrets.db_password}

Resource Limits

targets:
containers:
limited:
image: node:18

# Memory limits
memory: 512m # Memory limit
memorySwap: 1g # Memory + swap limit
memoryReservation: 256m # Soft limit

# CPU limits
cpus: "0.5" # Number of CPUs
cpuShares: 512 # CPU shares (relative)
cpusetCpus: "0,1" # CPU cores to use

# Other limits
pidsLimit: 100 # Process limit
ulimits:
nofile:
soft: 65535
hard: 65535

Security Configuration

User and Groups

targets:
containers:
secure:
image: node:18

# Run as specific user
user: "1000:1000" # UID:GID
# OR
user: appuser # Username

# Additional groups
groupAdd:
- docker
- video

Capabilities

targets:
containers:
capabilities:
image: alpine

# Add capabilities
capAdd:
- SYS_ADMIN
- NET_ADMIN

# Drop capabilities
capDrop:
- ALL

# Privileged mode (all capabilities)
privileged: false

Security Options

targets:
containers:
hardened:
image: alpine
securityOpt:
- no-new-privileges
- seccomp=unconfined
- apparmor=docker-default
readonlyRootfs: true

Docker Socket Access

targets:
containers:
docker-in-docker:
image: docker:dind
privileged: true
volumes:
- /var/run/docker.sock:/var/run/docker.sock

Custom Docker Configuration

Docker Host

targets:
containers:
remote:
image: alpine
dockerHost: tcp://remote-docker:2376
dockerCertPath: ~/.docker/certs

Registry Authentication

targets:
containers:
private:
image: registry.example.com/app:latest
registryAuth:
username: ${secrets.registry_user}
password: ${secrets.registry_password}

Real-World Examples

Development Environment

targets:
containers:
dev:
image: node:18
workdir: /app
volumes:
- .:/app
- node_modules:/app/node_modules
ports:
- "3000:3000"
- "9229:9229" # Debugger
env:
NODE_ENV: development
DEBUG: "*"
tty: true
stdin: true

Production Database

targets:
containers:
postgres:
image: postgres:15-alpine
restart: unless-stopped
volumes:
- postgres_data:/var/lib/postgresql/data
- ./backup:/backup
env:
POSTGRES_DB: production
POSTGRES_USER: appuser
POSTGRES_PASSWORD: ${secrets.db_password}
ports:
- "127.0.0.1:5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U appuser"]
interval: 10s
timeout: 5s
retries: 5

Build Environment

targets:
containers:
builder:
image: node:18
workdir: /build
volumes:
- .:/build:ro
- build_cache:/build/.cache
- dist:/build/dist
env:
CI: true
NPM_TOKEN: ${secrets.npm_token}
user: "1000:1000"
autoRemove: true

Troubleshooting

Container Debugging

# Check container status
docker ps -a

# View container logs
xec logs containers.app

# Execute debug commands
xec in containers.app "ps aux"
xec in containers.app "env | sort"

Common Issues

Image Not Found

# Ensure image exists
targets:
containers:
app:
image: node:18 # Use official images
# OR pull explicitly
imagePullPolicy: always

Permission Denied

# Fix volume permissions
targets:
containers:
fixed:
image: node:18
user: "$(id -u):$(id -g)" # Match host user
volumes:
- .:/app:rw,z # SELinux label if needed

Port Already in Use

# Use different ports
targets:
containers:
app:
ports:
- "3001:3000" # Map to different host port

Best Practices

1. Use Specific Tags

# Good - specific version
image: node:18.17.1-alpine

# Bad - latest tag
image: node:latest

2. Minimize Layers

# Combine related operations
targets:
containers:
efficient:
image: alpine
command: sh -c "apk add --no-cache git && git clone repo"

3. Use .dockerignore

# .dockerignore
node_modules
.git
*.log
.env

4. Security First

targets:
containers:
secure:
image: alpine
user: nobody # Non-root user
readonlyRootfs: true # Read-only filesystem
capDrop: [ALL] # Drop all capabilities

5. Resource Limits

targets:
containers:
limited:
image: node:18
memory: 512m # Always set limits
cpus: "0.5"

Next Steps

See Also