← Назад к вопросам

Кто работает с Dockerfile

1.7 Middle🔥 131 комментариев
#Основы Java

Комментарии (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.

Кто работает с Dockerfile | PrepBro