Gymterview
middle

Как Docker используется в CI/CD?

Docker в CI/CD обеспечивает воспроизводимость сборки, единообразие окружения и стандартизацию доставки артефактов через Docker-образы.

1. Единообразная среда сборки

Сборка проекта выполняется внутри контейнера, что гарантирует одинаковый результат на машине разработчика и CI-сервере:

Пример
docker run --rm -v $(pwd):/app -w /app maven:3.9-eclipse-temurin-17 mvn package

2. Сборка и публикация Docker-образа

Пример
# Сборка с тегированием
docker build -t registry.example.com/myapp:${GIT_COMMIT_SHA} .
docker build -t registry.example.com/myapp:latest .

# Отправка в реестр
docker push registry.example.com/myapp:${GIT_COMMIT_SHA}
docker push registry.example.com/myapp:latest

3. Пример GitLab CI/CD

Пример .gitlab-ci.yml
stages:
  - test
  - build
  - deploy

test:
  stage: test
  image: maven:3.9-eclipse-temurin-17
  script:
    - mvn test
  cache:
    paths:
      - .m2/repository

build:
  stage: build
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

deploy:
  stage: deploy
  script:
    - docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - docker stop myapp || true
    - docker rm myapp || true
    - docker run -d --name myapp -p 8080:8080 $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

4. Пример GitHub Actions

Пример workflow
name: Build and Push
on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: myuser/myapp:${{ github.sha }}

5. Тестирование с Testcontainers

Библиотека Testcontainers позволяет запускать Docker-контейнеры в интеграционных тестах:

Пример кода
@SpringBootTest
@Testcontainers
class UserRepositoryTest {

    @Container
    static PostgreSQLContainer<?> postgres =
        new PostgreSQLContainer<>("postgres:16-alpine")
            .withDatabaseName("testdb")
            .withUsername("test")
            .withPassword("test");

    @DynamicPropertySource
    static void configureProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", postgres::getJdbcUrl);
        registry.add("spring.datasource.username", postgres::getUsername);
        registry.add("spring.datasource.password", postgres::getPassword);
    }

    @Test
    void shouldSaveUser() {
        // тест с реальной базой данных
    }
}

На собеседовании: покажите, что Docker используется на всех этапах CI/CD: сборка в контейнере (единообразие), упаковка в образ (артефакт), тестирование с Testcontainers (интеграционные тесты с реальными БД), деплой образа. Знание Testcontainers — большой плюс для Java-разработчика.