Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Опыт работы с Docker и Dockerfile: мой путь
Работа с Docker - неотъемлемая часть моей повседневной разработки уже 5+ лет. Это уже перестало быть экзотикой и стало стандартом в индустрии.
Когда я начал работать с Docker
Мой путь начался примерно в 2018-2019, когда контейнеризация стала стандартом в компаниях среднего размера. В то время это было инновационно, но сейчас это базовый навык backend-разработчика.
Типовой Dockerfile для Java приложения
Вот структура, которую я использую часто:
# Multi-stage build - оптимизация размера образа
FROM maven:3.9-eclipse-temurin-21 AS builder
WORKDIR /app
COPY pom.xml .
# Кэшируем зависимости
RUN mvn dependency:resolve
COPY src/ src/
RUN mvn clean package -DskipTests
# Финальный образ
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY --from=builder /app/target/application.jar app.jar
# Не запускаемся как root
RUN useradd -m appuser
USER appuser
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:8080/health || exit 1
ENTRYPOINT ["java", "-jar", "app.jar"]
Почему эта структура:
- Multi-stage: исходный код не попадает в финальный образ
- Alpine: минимальный размер JRE образа
- Кэширование зависимостей: быстрее пересобирать при изменении кода
- Non-root user: безопасность
- HEALTHCHECK: Kubernetes может перезагружать контейнер
Другой вариант: Layered JAR (Spring Boot)
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
# Распаковываем слои Spring Boot JAR
ARG JAR_FILE=target/application.jar
COPY ${JAR_FILE} app.jar
RUN java -Djarmode=layertools -jar app.jar extract
# Копируем слои - зависимости кэшируются отдельно
COPY --chown=nobody:nobody spring-boot-loader/ ./
COPY --chown=nobody:nobody dependencies/ ./
COPY --chown=nobody:nobody snapshot-dependencies/ ./
COPY --chown=nobody:nobody application/ ./
USER nobody
EXPOSE 8080
ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]
Преимущество:
- Зависимости изменяются редко → слой кэшируется
- Код изменяется часто → отдельный слой
- Сборка на 50% быстрее при изменении только кода
docker-compose.yml для локальной разработки
version: '3.8'
services:
app:
build: .
ports:
- "8080:8080"
environment:
SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/appdb
SPRING_DATASOURCE_USERNAME: postgres
SPRING_DATASOURCE_PASSWORD: postgres
depends_on:
postgres:
condition: service_healthy
volumes:
- ./src:/app/src # Для hot-reload
networks:
- app-network
postgres:
image: postgres:16-alpine
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: appdb
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- app-network
redis:
image: redis:7-alpine
ports:
- "6379:6379"
networks:
- app-network
volumes:
postgres-data:
networks:
app-network:
driver: bridge
Как использую:
docker compose up -d # Запустить все сервисы
docker compose logs -f app # Логи приложения
docker compose ps # Состояние контейнеров
docker compose down -v # Выключить и удалить данные
Оптимизации Dockerfile
1. Кэширование слоев
# ✅ Хорошо - зависимости кэшируются
COPY pom.xml .
RUN mvn dependency:resolve
COPY src/ src/
RUN mvn clean package
# ❌ Плохо - при каждом изменении пересчитываются зависимости
COPY . .
RUN mvn clean package
2. Размер образа
# ❌ Плохо: 500 MB
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y openjdk-21-jre
RUN apt-get install -y curl git
# ✅ Хорошо: 100 MB
FROM eclipse-temurin:21-jre-alpine
# ✅ Очень хорошо для production: 50 MB
FROM eclipse-temurin:21-jre-alpine
RUN apk del --no-cache tzdata
3. Security scanning
# Сканируем образ на уязвимости
docker scan my-app:latest
# или
trivy image my-app:latest
CI/CD с Docker
# .github/workflows/docker.yml
name: Build and Push Docker Image
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: |
${{ secrets.DOCKER_USERNAME }}/my-app:latest
${{ secrets.DOCKER_USERNAME }}/my-app:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
Как я работаю с Docker в текущих проектах
Ежедневно:
- Пишу/обновляю Dockerfile для новых микросервисов
- Использую
docker composeдля локальной разработки - Проверяю логи контейнеров при отладке
- Пересобираю образы после изменения зависимостей
Еженедельно:
- Оптимизирую размер образов
- Обновляю base images (security patches)
- Сканирую на уязвимости
- Тестирую в Kubernetes
Ежемесячно:
- Пересматриваю стратегию multi-stage build
- Анализирую performance metrics контейнеров
- Обновляю Java версии
Кто еще работает с Docker в команде
DevOps инженеры:
- Создают базовые образы
- Настраивают registry (Docker Hub, ECR)
- Управляют Kubernetes deployment'ами
QA инженеры:
- Запускают тесты в Docker контейнерах
- Тестируют в docker compose окружении
- Проверяют совместимость на разных версиях
Мой уровень (Backend Developer):
- Пишу Dockerfile для своих сервисов
- Отлаживаю в docker compose
- Оптимизирую производительность контейнера
- Работаю с логами контейнеров
Основные команды, которые я использую ежедневно
# Сборка
docker build -t my-app:latest .
docker build -t my-app:latest --build-arg ENV=prod .
# Запуск
docker run -p 8080:8080 my-app:latest
docker run -it --rm my-app:latest bash
# Отладка
docker logs -f container_id
docker exec -it container_id bash
# Очистка
docker system prune -a # Удалить все неиспользуемые образы
Редкие, но важные случаи
# Для локальной разработки с hot-reload
FROM maven:3.9 AS dev
WORKDIR /app
CMD ["mvn", "spring-boot:run"]
# Для production с минимальной стартовой стоимостью
FROM gcr.io/distroless/java21
Итог: Работа с Docker - это не опциональный скилл, это базис современной разработки. Каждый Java разработчик должен писать свой Dockerfile, понимать layers, кэширование и security practices.