Docker 위에 Kafka를 standalone으로 실행하기
동기
Kafka를 자주 테스트할 일이 있어서, Dockerfile을 이용해 컨테이너를 만드는 방법을 알아보고 정리해 보았다.
더 나은 방법이 분명 더 있을텐데... 다른 글에서 docker compose를 이용해서 좀더 개선을 해볼 예정이다.
사전 지식
이제 막 공부를 시작한 입장에서, 사전지식이라고 정리할 내용은 거의 없으나.. 그래도 조금이라도 정리를 해본다.
docker 명령어
sudo service docker start
: 도커 데몬 시작docker pull <image name>
: 도커 이미지 내려받기docker images
: 도커 이미지 목록 보기docker ps
: 도커 컨테이너 목록 보기docker ps --all
: 모든 도커 컨테이너 목록 보기 (멈춘 컨테이너까지 보여준다.)docker rmi <image name>
: 도커 이미지 삭제docker rm <container name>
: 도커 컨테이너 삭제docker stop <container name>
: 도커 컨테이너 중지docker run --rm --name <container name> -p <host port>:<container port> --network <network name> <image name>
: 도커 이미지를 컨테이너로 실행(인스턴스화)하기- rm 옵션 : 컨테이너가 종료되면 바로 삭제한다.
- name 옵션 : 컨테이너 이름을 지정한다.
- p 옵션 : 호스트 포트에 컨테이너 포트를 맵핑한다. 부가적으로, 대문자 P 옵션은 Dockerfile에 EXPOSE 설정된 포트를 임의의 호스트 포트에 자동으로 맵핑하는 옵션이다.
- network 옵션 : 컨테이너가 속할 네트워크 이름을 지정한다.
docker exec -it <container name> /bin/bash
: 컨테이너에 /bin/bash의 새 프로세스를 띄우고, 호스트의 표준입출력을 연결해 접속할 수 있게 해준다.docker build -t <image name> <dockerfile path>
: Dockerfile을 이미지로 빌드한다.docker network create <network name>
: 네트워크를 생성한다.docker network inspect <network name>
: 네트워크 구성을 확인한다.docker network list
: 네트워크 목록을 확인한다.docker network prune
: 아무 컨테이너도 참여하고 있지 않은, 미사용 상태의 네트워크를 정리한다.
Dockerfile 명령어
FROM <image name>
: 특정 이미지를 상속받아 시작한다.ENV <key>=<value>
: 환경변수를 지정한다.EXPOSE <port>
: 호스트와 연결할 포트를 명시한다.RUN <command>
: 빌드타임에 커맨드를 실행한다.WORKDIR <path>
: 현재 작업 디렉토리를 변경한다.COPY <source> <destinatoin>
: 빌드타임에 파일을 복사한다.CMD <command>
: 런타임에 커맨드를 실행한다.
구조
로컬에서 개발 테스트에 사용할 목적이므로, Kafka는 클러스터를 구성하지 않고, 스탠드얼론으로 설치할 예정이다.
이미지는 주키퍼 서버 1대, 카프카 서버 1대, 카프카 클라이언트/콘솔 용도 1대로 총 3개의 이미지를 작성할 예정이다.
+-- zk : 주키퍼 서버 이미지 작성용
| +-- Dockerfile
+-- kf : 카프카 서버 이미지 작성용
| +-- Dockerfile
| +-- server.properties
+-- kfcli : 카프카 클라이언트/콘솔 용도 이미지 작성용
+-- Dockerfile
외부 접속 허용을 위한 포트 열기
다음과 같이 관리자 권한을 받은 powershell에서 실행해준다.
netsh interface portproxy delete v4tov4 listenport="2181"
netsh interface portproxy delete v4tov4 listenport="9092"
$wslIp=(wsl -d Ubuntu -e sh -c "ip addr show eth0 | grep 'inet\b' | awk '{print `$2}' | cut -d/ -f1")
netsh interface portproxy add v4tov4 listenport="2181" connectaddress="$wslIp" connectport="2181"
netsh interface portproxy add v4tov4 listenport="9092" connectaddress="$wslIp" connectport="9092"
network 생성
컨테이너들이 참여하여 서로 연결할 수 있는 네트워크를 미리 만들어준다.
docker network create kfnet
zk/Dockerfile
주키퍼 서버 이미지의 Dockerfile은 다음과 같다.
FROM ubuntu:20.04
ENV TZ=Asia/Seoul
EXPOSE 2181
RUN apt-get update
RUN apt-get install -y curl openjdk-13-jre
WORKDIR /root
RUN mkdir -p /var/kafka
RUN curl https://dlcdn.apache.org/kafka/2.8.0/kafka_2.13-2.8.0.tgz --output kafka.tgz
RUN tar xvzf kafka.tgz --directory=/var/kafka --strip-components=1
CMD /var/kafka/bin/zookeeper-server-start.sh /var/kafka/config/zookeeper.properties
이 Dockerfile은 docker build -t zk zk/
와 같이 명령을 주어 빌드할 예정이고, 다음과 같이 실행한다.
docker run --rm --name zk-inst -p 2181:2181 --network kfnet zk
kf/Dockerfile 과 kf/server.properties
카프카 서버 이미지의 Dockerfile은 다음과 같다.
FROM ubuntu:20.04
ENV TZ=Asia/Seoul
EXPOSE 9092
RUN apt-get update
RUN apt-get install -y curl openjdk-13-jre
WORKDIR /root
RUN mkdir -p /var/kafka
RUN curl https://dlcdn.apache.org/kafka/2.8.0/kafka_2.13-2.8.0.tgz --output kafka.tgz
RUN tar xvzf kafka.tgz --directory=/var/kafka --strip-components=1
COPY server.properties /var/kafka/config/server.properties
CMD /var/kafka/bin/kafka-server-start.sh /var/kafka/config/server.properties
카프카 서버는 주키퍼 서버에 연결해야 하는데, 이를 위해 server.properties를 수정하여 주키퍼 서버의 주소를 설정해주어야 한다.
같은 네트워크에 속한 컨테이너들끼리는, 컨테이너 이름으로 서로를 찾을 수 있기 때문에, 컨테이너 이름을 주키퍼 주소에 지정해준다.
...(기본 server.properties에서 아래만 추가/수정해준다.)...
listeners=PLAINTEXT://:9092
zookeeper.connect=zk-inst:2181
이미지 빌드는 docker build -t kf kf/
와 같이 명령을 주어 빌드하고, 다음과 같이 컨테이너를 실행한다.
docker run --rm --name kf-inst -p 9092:9092 --network kfnet kf
kfcli/Dockerfile
이제 마지막으로 카프카 클라이언트 이미지를 작성해준다.
FROM ubuntu:20.04
ENV TZ=Asia/Seoul
RUN apt-get update
RUN apt-get install -y curl openjdk-13-jre
WORKDIR /root
RUN mkdir -p /var/kafka
RUN curl https://dlcdn.apache.org/kafka/2.8.0/kafka_2.13-2.8.0.tgz --output kafka.tgz
RUN tar xvzf kafka.tgz --directory=/var/kafka --strip-components=1
WORKDIR /var/kafka
ENTRYPOINT /bin/bash
역시 docker build -t kfcli kfcli/
처럼 빌드하고, 다음과 같이 컨테이너화 하여 실행하면, 해당 쉘 안에서 카프카 클라이언트 실행이 가능하다.
docker run --rm --name kfcli-inst --network kfnet -it kfcli
간단하게, 아래처럼 토픽을 생성해보면 잘 동작하는 것을 알 수 있다.
bin/kafka-topics.sh --bootstrap-server kf-inst:9092 --create --topic hello-kafka
bin/kafka-topics.sh --bootstrap-server kf-inst:9092 --list
참고자료
- DalSeo : Dockerfile에서 자주 쓰이는 명령어
- DalSeo : Docker 네트워크 사용법
- 킴루코 : Dockerfile에서 EXPOSE와 "docker run -p" 명령의 차이점
- Stackoverflow : Can't connect to WSL2 localhost server from WSL2 docker container
- Loner의 학습노트 : 도커 컨테이너끼리 연결하기
- ㅍㅍㅋㄷ : docker container에 접속하기
- ㅍㅍㅋㄷ : docker container ip 확인
- ㅍㅍㅋㄷ : docker network 구조(1) - docker0와 container network 구조
- ㅍㅍㅋㄷ : docker network 구조(2) - container network 방식 4가지
- ㅍㅍㅋㄷ : docker network 구조(3) - container 외부 통신 구조
- ㅍㅍㅋㄷ : docker network 구조(4) - container link 구조