# Docker ## Навигация - [🏠 Главная страница курса](../../../README.md) - [📚 Модуль 3](../README.md) --- ## Основы Docker **Docker** — платформа для разработки, доставки и запуска приложений в контейнерах. ## Архитектура Docker ``` ┌─────────────────────────────────────┐ │ Docker Client │ ├─────────────────────────────────────┤ │ Docker Daemon │ │ ┌─────────────┐ ┌─────────────────┐ │ │ │ Images │ │ Containers │ │ │ └─────────────┘ └─────────────────┘ │ ├─────────────────────────────────────┤ │ Container Runtime │ └─────────────────────────────────────┘ ``` ## Dockerfile **Dockerfile** — текстовый файл с инструкциями для создания образа. ### Технический пример - Dockerfile для Spring Boot приложения: ```dockerfile # Многоэтапная сборка для оптимизации размера образа # Этап 1: Сборка приложения FROM maven:3.8.6-openjdk-17-slim AS build # Установка рабочей директории WORKDIR /app # Копирование файлов pom.xml для кэширования зависимостей COPY pom.xml . COPY src ./src # Сборка приложения RUN mvn clean package -DskipTests # Этап 2: Создание финального образа FROM openjdk:17-jre-slim # Установка рабочей директории WORKDIR /app # Создание пользователя для безопасности RUN groupadd -r appuser && useradd -r -g appuser appuser # Копирование собранного JAR файла COPY --from=build /app/target/*.jar app.jar # Изменение владельца файлов RUN chown -R appuser:appuser /app USER appuser # Открытие порта EXPOSE 8080 # Переменные окружения ENV JAVA_OPTS="-Xmx512m -Xms256m" ENV SPRING_PROFILES_ACTIVE=production # Health check HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD curl -f http://localhost:8080/actuator/health || exit 1 # Запуск приложения ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"] ``` ### Dockerfile для микросервиса на Node.js: ```dockerfile # Базовый образ Node.js FROM node:18-alpine AS base # Установка рабочей директории WORKDIR /app # Установка системных зависимостей RUN apk add --no-cache \ dumb-init \ curl # Создание пользователя для безопасности RUN addgroup -g 1001 -S nodejs && \ adduser -S nextjs -u 1001 # Этап установки зависимостей FROM base AS deps COPY package*.json ./ RUN npm ci --only=production && npm cache clean --force # Этап сборки FROM base AS builder COPY package*.json ./ RUN npm ci COPY . . RUN npm run build # Финальный этап FROM base AS runner ENV NODE_ENV=production # Копирование зависимостей COPY --from=deps /app/node_modules ./node_modules COPY --from=builder /app/dist ./dist COPY --from=builder /app/public ./public # Копирование конфигурационных файлов COPY --from=builder /app/package.json ./package.json # Изменение владельца файлов RUN chown -R nextjs:nodejs /app USER nextjs # Открытие порта EXPOSE 3000 # Health check HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD curl -f http://localhost:3000/health || exit 1 # Запуск приложения ENTRYPOINT ["dumb-init", "--"] CMD ["node", "dist/index.js"] ``` ## Docker Compose **Docker Compose** — инструмент для определения и запуска многоконтейнерных приложений. ### Docker Compose для микросервисной архитектуры: ```yaml version: '3.8' services: # API Gateway api-gateway: build: context: ./api-gateway dockerfile: Dockerfile ports: - "8080:8080" environment: - SPRING_PROFILES_ACTIVE=docker - EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://eureka:8761/eureka/ depends_on: - eureka - user-service - order-service - payment-service networks: - microservices-network healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"] interval: 30s timeout: 10s retries: 3 # Service Discovery eureka: image: steeltoeoss/eureka-server:latest ports: - "8761:8761" environment: - EUREKA_CLIENT_REGISTER_WITH_EUREKA=false - EUREKA_CLIENT_FETCH_REGISTRY=false networks: - microservices-network # User Service user-service: build: context: ./user-service dockerfile: Dockerfile ports: - "8081:8080" environment: - SPRING_PROFILES_ACTIVE=docker - SPRING_DATASOURCE_URL=jdbc:postgresql://user-db:5432/userdb - SPRING_DATASOURCE_USERNAME=user - SPRING_DATASOURCE_PASSWORD=password - EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://eureka:8761/eureka/ depends_on: - user-db - eureka networks: - microservices-network healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"] interval: 30s timeout: 10s retries: 3 # Databases user-db: image: postgres:15-alpine environment: - POSTGRES_DB=userdb - POSTGRES_USER=user - POSTGRES_PASSWORD=password volumes: - user_data:/var/lib/postgresql/data - ./init-scripts/user-db-init.sql:/docker-entrypoint-initdb.d/init.sql networks: - microservices-network healthcheck: test: ["CMD-SHELL", "pg_isready -U user -d userdb"] interval: 10s timeout: 5s retries: 5 # Message Queue rabbitmq: image: rabbitmq:3.11-management-alpine ports: - "5672:5672" - "15672:15672" environment: - RABBITMQ_DEFAULT_USER=admin - RABBITMQ_DEFAULT_PASS=admin volumes: - rabbitmq_data:/var/lib/rabbitmq networks: - microservices-network healthcheck: test: ["CMD", "rabbitmq-diagnostics", "ping"] interval: 30s timeout: 10s retries: 3 # Monitoring prometheus: image: prom/prometheus:latest ports: - "9090:9090" volumes: - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml - prometheus_data:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus' - '--web.console.libraries=/etc/prometheus/console_libraries' - '--web.console.templates=/etc/prometheus/consoles' - '--storage.tsdb.retention.time=200h' - '--web.enable-lifecycle' networks: - microservices-network grafana: image: grafana/grafana:latest ports: - "3000:3000" environment: - GF_SECURITY_ADMIN_PASSWORD=admin volumes: - grafana_data:/var/lib/grafana - ./monitoring/grafana/dashboards:/etc/grafana/provisioning/dashboards - ./monitoring/grafana/datasources:/etc/grafana/provisioning/datasources networks: - microservices-network volumes: user_data: rabbitmq_data: prometheus_data: grafana_data: networks: microservices-network: driver: bridge ``` ## Команды Docker ### Основные команды: ```bash # Сборка образа docker build -t myapp:latest . # Запуск контейнера docker run -p 3000:3000 myapp:latest # Просмотр запущенных контейнеров docker ps # Просмотр всех контейнеров docker ps -a # Остановка контейнера docker stop # Удаление контейнера docker rm # Просмотр образов docker images # Удаление образа docker rmi ``` ### Продвинутые команды: ```bash # Запуск в фоновом режиме docker run -d -p 3000:3000 myapp:latest # Подключение к контейнеру docker exec -it /bin/bash # Просмотр логов docker logs # Мониторинг ресурсов docker stats ``` ## Лучшие практики Docker ### 1. Оптимизация размера образа ```dockerfile # Используйте многоэтапную сборку FROM node:18-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build FROM node:18-alpine AS production WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY --from=builder /app/dist ./dist CMD ["npm", "start"] ``` ### 2. Безопасность ```dockerfile # Создайте пользователя без root прав RUN addgroup -g 1001 -S nodejs RUN adduser -S nextjs -u 1001 USER nextjs ``` ### 3. Кэширование слоев ```dockerfile # Копируйте package.json перед исходным кодом COPY package*.json ./ RUN npm ci COPY . . ``` ### 4. Health Checks ```dockerfile HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD curl -f http://localhost:3000/health || exit 1 ```