Docker 서비스 컨테이너와 통신하기
Docker 서비스 컨테이너와 통신하기
Docker 서비스 컨테이너를 사용해서 데이터베이스, 웹 서비스, 메모리 캐시, 기타 도구를 워크플로우에 연결하는 방법을 알려드릴게요. 서비스 컨테이너를 이용하면 워크플로우에서 애플리케이션을 테스트하거나 운영하는 데 필요한 서비스를 간편하게 호스팅할 수 있어요.
출처: 문서
본문
Communicating with Docker service containers
서비스 컨테이너는 워크플로우에서 애플리케이션을 테스트하거나 운영할 때 필요한 서비스를 호스팅할 수 있는 간단하고 이식 가능한 방법을 제공하는 Docker 컨테이너예요. 예를 들어 워크플로우가 데이터베이스와 메모리 캐시에 대한 접근이 필요한 통합 테스트를 실행해야 할 수 있어요.
워크플로우의 각 job에 대해 서비스 컨테이너를 구성할 수 있어요. GitHub는 워크플로우에 구성된 각 서비스에 대해 새 Docker 컨테이너를 만들고, job이 완료되면 서비스 컨테이너를 파괴해요. job의 단계는 같은 job의 일부인 모든 서비스 컨테이너와 통신할 수 있어요. 하지만 복합 액션 안에서는 서비스 컨테이너를 만들고 사용할 수 없어요.
[!NOTE] 워크플로우가 Docker 컨테이너 액션, job 컨테이너 또는 서비스 컨테이너를 사용한다면 Linux 러너를 사용해야 해요.
- GitHub에서 호스팅하는 러너를 사용한다면 Ubuntu 러너를 사용해야 해요.
- 자체 호스팅 러너를 사용한다면 러너로 Linux 머신을 사용해야 하고 Docker가 설치되어 있어야 해요.
워크플로우의 job을 러너 머신에서 직접 실행하거나 Docker 컨테이너에서 실행하도록 구성할 수 있어요. job이 러너 머신에서 직접 실행되는지 컨테이너에서 실행되는지에 따라 job과 서비스 컨테이너 간의 통신이 달라져요.
Running jobs in a container
컨테이너에서 job을 실행하면 GitHub는 Docker의 사용자 정의 브리지 네트워크(user-defined bridge networks)를 사용해서 서비스 컨테이너를 job에 연결해요. 자세한 내용은 Docker 문서의 Bridge network driver를 참고하세요.
job과 서비스를 컨테이너에서 실행하면 네트워크 접근이 단순해져요. 워크플로우에서 구성한 레이블을 사용해서 서비스 컨테이너에 접근할 수 있어요. 서비스 컨테이너의 호스트 이름은 레이블 이름에 자동으로 매핑돼요. 예를 들어 redis 레이블로 서비스 컨테이너를 만들면 서비스 컨테이너의 호스트 이름은 redis가 돼요.
서비스 컨테이너에 대한 포트를 구성할 필요는 없어요. 기본적으로 같은 Docker 네트워크의 일부인 모든 컨테이너는 서로에게 모든 포트를 노출하고, Docker 네트워크 외부에는 포트가 노출되지 않아요.
Running jobs on the runner machine
러너 머신에서 job을 직접 실행할 때는 localhost:<port> 또는 127.0.0.1:<port>를 사용해서 서비스 컨테이너에 접근할 수 있어요. GitHub는 서비스 컨테이너에서 Docker 호스트로의 통신을 가능하게 하도록 컨테이너 네트워크를 구성해요.
job이 러너 머신에서 직접 실행될 때, Docker 컨테이너에서 실행되는 서비스는 기본적으로 포트를 러너의 job에 노출하지 않아요. 서비스 컨테이너의 포트를 Docker 호스트에 매핑해야 해요. 자세한 내용은 Communicating with Docker service containers 문서를 참고하세요.
Creating service containers
services 키워드를 사용해서 워크플로우의 job의 일부인 서비스 컨테이너를 만들 수 있어요. 자세한 내용은 jobs.<job_id>.services 문서를 참고하세요.
이 예시는 container-job이라는 job에 redis라는 서비스를 만듭니다. 이 예시의 Docker 호스트는 node:16-bullseye 컨테이너예요.
name: Redis container example
on: push
jobs:
# Label of the container job
container-job:
# Containers must run in Linux based operating systems
runs-on: ubuntu-latest
# Docker Hub image that `container-job` executes in
container: node:16-bullseye
# Service containers to run with `container-job`
services:
# Label used to access the service container
redis:
# Docker Hub image
image: redis
Mapping Docker host and service container ports
job이 Docker 컨테이너에서 실행된다면 호스트나 서비스 컨테이너의 포트를 매핑할 필요가 없어요. job이 러너 머신에서 직접 실행된다면 필요한 서비스 컨테이너 포트를 호스트 러너 머신의 포트에 매핑해야 해요.
ports 키워드를 사용해서 서비스 컨테이너 포트를 Docker 호스트에 매핑할 수 있어요. 자세한 내용은 jobs.<job_id>.services 문서를 참고하세요.
Value of ports |
Description |
|---|---|
8080:80 |
Maps TCP port 80 in the container to port 8080 on the Docker host. |
8080:80/udp |
Maps UDP port 80 in the container to port 8080 on the Docker host. |
8080/udp |
Maps a randomly chosen port on the Docker host to UDP port 8080 in the container. |
ports 키워드를 사용해서 포트를 매핑하면 GitHub는 --publish 명령을 사용해서 컨테이너의 포트를 Docker 호스트에 게시해요. 자세한 내용은 Docker 문서의 Docker container networking을 참고하세요.
컨테이너 포트를 지정하되 Docker 호스트 포트를 지정하지 않으면 컨테이너 포트가 사용 가능한 포트에 무작위로 할당돼요. GitHub는 할당된 컨테이너 포트를 서비스 컨테이너 컨텍스트에 설정해요. 예를 들어 redis 서비스 컨테이너에 대해 Docker 호스트 포트 5432를 구성했다면 job.services.redis.ports[5432] 컨텍스트를 사용해서 해당 컨테이너 포트에 접근할 수 있어요. 자세한 내용은 Contexts reference 문서를 참고하세요.
Example mapping Redis ports
이 예시는 서비스 컨테이너 redis 포트 6379를 Docker 호스트 포트 6379에 매핑해요.
name: Redis Service Example
on: push
jobs:
# Label of the container job
runner-job:
# You must use a Linux environment when using service containers or container jobs
runs-on: ubuntu-latest
# Service containers to run with `runner-job`
services:
# Label used to access the service container
redis:
# Docker Hub image
image: redis
#
ports:
# Opens tcp port 6379 on the host and service container
- 6379:6379
Authenticating with image registries
이미지 레지스트리로 인증해야 하는 경우 서비스 컨테이너에 대한 자격 증명을 지정할 수 있어요. 이렇게 하면 비공개 레지스트리의 이미지를 사용하거나 DockerHub 속도 제한을 높일 수 있어요.
Docker Hub와 GitHub Container registry로 인증하는 예시는 다음과 같아요.
jobs:
build:
services:
redis:
# Docker Hub image
image: redis
ports:
- 6379:6379
credentials:
username: ${{ secrets.dockerhub_username }}
password: ${{ secrets.dockerhub_password }}
db:
# Private registry image
image: ghcr.io/octocat/testdb:latest
credentials:
username: ${{ github.repository_owner }}
password: ${{ secrets.ghcr_password }}
Customizing service container entrypoints and commands
기본적으로 서비스 컨테이너는 Docker 이미지에 정의된 엔트리포인트와 명령으로 실행돼요. entrypoint와 command 키를 사용해서 이를 재정의할 수 있어요. 이것은 서비스(예: 데이터베이스)에 플래그를 전달해야 하거나 사용자 지정 래퍼 이미지를 빌드하지 않고 이미지 엔트리포인트를 완전히 교체해야 할 때 유용해요.
command 키는 이미지의 기본 명령(CMD)을 재정의해요. 대부분의 시나리오에서는 command만 있으면 돼요—이미지에 올바른 엔트리포인트가 이미 있으므로 플래그만 전달하면 되거든요.
services:
mysql:
image: mysql:8
command: --sql_mode=STRICT_TRANS_TABLES --max_allowed_packet=512M
env:
MYSQL_ROOT_PASSWORD: test
ports:
- 3306:3306
entrypoint 키는 이미지의 ENTRYPOINT를 재정의해요. command와 결합해서 사용자 지정 엔트리포인트에 인수를 전달할 수 있어요.
services:
etcd:
image: quay.io/coreos/etcd:v3.5.17
entrypoint: etcd
command: >-
--listen-client-urls http://0.0.0.0:2379
--advertise-client-urls http://0.0.0.0:2379
ports:
- 2379:2379
이름 지정과 동작은 Docker Compose와 일치해요. 자세한 내용은 jobs.<job_id>.services.<service_id>.command 및 jobs.<job_id>.services.<service_id>.entrypoint 문서를 참고하세요.