Redis를 Docker Compose로 실행하기

구본식·2023년 1월 18일
1
post-thumbnail

1. 문제 상황

앞 포스터까지 Docker를 이용하여 Jenkins를 띄우고 DockerHub에 올라가 있는 .jar 실행파일(프로젝트)까지 Docker로 띄우도록 구성하였다.

프로젝트내에서 Redis를 사용하고 있는데 기존에는 아래 그림과 같이 localhost(127.0.0.1)Redis에 접속하였다.

이 상태에서 Docker를 이용하여 프로젝트 이미지를 컨테이너로 띄우게 되면 Redis에 접근할수 없었다.
(운영 EC2서버에 별도의 Redis 서버를 설치하여 구동하였음에도)

왜냐하면 도커 컨테이너독립적인 private 네트워크 IP를 가지고 있기 때문이다. localhost로 설정하게 되면 스프링 이미지가 띄어져있는 도커 컨테이너를 가르키기 때문이다.
즉 EC2의 localhost와 도커 컨테이너의 localhost가 다르기 때문에 Redis에 접속할수 없는 것이였다.!

찾아보던중 여러가지의 해결방안이 존재하였다.
1. Redis도 Docker로 띄운후 Docker compose를 이용하여 Redis, 스프링 컨테이너를 같이 관리하기
2. docker 컨테이너안에서 호스트(localhost)의 redis 서버에 접근하기
등 다양한 방식들이 존재하였다.

나는 그중에서 첫번째 방식을 선택하여 해결하였다.

문제 해결을 위해 필요한 공부를 간략히 진행하였다. 추후 더 깊게 공부할수 있는 기회가 있으면 해볼것이다.


2. Docker Compose란

Docker compose란 여러 개의 컨테이너를 동시에 연계해서 구동할수 있게 해주는 컨테이너 툴이다.

어플리케이션을 구동하기 위해서 서비스(실행파일), DB, Redis등 여러개의 구성요소가 필요하다. 이러한 필요한 sevice들을 연결시켜(통신설정등) 컨테이너로 띄울수 있다. 하지만 이러한 방식이 불편하여 나온것이 Docker compose이다.

독립적인 컨테이너를 실행,종료 시키기 위해서 각각의 명령어 대신 하나의 docker compose명령어를 통해 컨테이너들을 실행,종료 시킬수 있다.

기본적으로 Docker Compose는 하나의 디폴트 네트워크에 모든 컨테이너를 연결한다.
그렇기 때문에 같은 Docker Compose안에 속해있는 컨테이너들은 동일한 네트워크 IP 영역을 사용하기 때문에 자유롭게 통신이 가능하다.
디폴트 네트워크(같은 Docker Compose)안에서 컨테이너간의 통신에서는 지정한 호스트명을 통해 가능하게 된다.

또한 다른 Docker Compose안에 있는 컨테이너끼리도 네트워크 옵션을 통해 통신이 가능하다.


3. docker-compose.yml 작성

Docker compose를 사용하기 위해서는 지정된 docker-compose yaml 문법을 사용해야된다. 해당 문법을 이용하여 .yml파일을 작성하면 되는것이다.

해당 파일에 Docker 컨테이너들의 관한 실행 옵션 등을 작성하게 된다.
아래는 작성해본 compose 파일이고 프로젝트의 최상의디렉토리 위치에 정의하였다.

version: "3.0"
services:
  web:
    image: bonsik/codebox-project-images:1.0
    container_name: codebox
    ports:
      - 8888:8888

  redis:
    image: redis:alpine
    container_name: redis_boot
    command: redis-server --port 6379
    hostname: redis
    ports:
      - 6379:6379
  • 전 포스터에서 구현한것과 같이 DockerHub를 통해 Spring 이미지를 받아오기 때문에 Dockerfile에 대한 build가 필요없다고 생각하였다.
    그래서 DockerHub로 부터 Pull한 image의 이름을 image옵션에 정의하였다.

  • Docker를 통해 Redis를 띄우기 위해 사용할 Redis 기본 이미지를 지정하였고
    hostname: redis로 설정하여 추후 스프링 서비스가 Redis에 접근할때 host이름Redis로 사용하면 된다.

    application.yml 변경


3. 운영 서버

현재까지 프로젝트의 CI/CD 흐름도를 간단히 정리하자면
1. GitHub push
2. GitWebhooks를 통해 EC2 Jenkins server에 알림
3. Jenkins Pipeline 시작
gitclone -> test -> build -> docker image 생성 ->
dockerHub push -> 운영서버 deploy.sh 실행(실행중인 컨테이너 종료,이미지 pull, 컨테이너 시작)

처럼 흘러가게 된다.
여기에 마지막 단계인 deploy.sh에서 기존에는 스프링 이미지만 컨테이너로 실행하였지만 docker-compose.yml파일을 사용하여 스프링 서비스 컨테이너, Redis 컨테이너가 함께 실행되고 통신,관리 될수 있도록 구현하였다.

그렇기 때문에 운영서버에 Docker Compose를 사용할수 있게 설치하였다.

3.1 Docker Compose 설치

//docker compose 설치
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

//sudo 없이 docker compose 명령어를 사용할수 있게 권한 부여
chmod +x /usr/local/bin/docker-compose

//설치된 docker compose 버전 확인
docker-compose --version

3.2 Deploy.sh 수정

# 가동중인 awsstudy 도커 중단 및 삭제
docker ps -a -q --filter "name=codebox" | grep -q . && docker stop codebox && docker rm codebox | true

# 기존 이미지 삭제
docker rmi bonsik/codebox-project-images:1.0

# 도커허브 이미지 pull
docker pull bonsik/codebox-project-images:1.0

# 도커 컴포즈 실행 - 수정
docker-compose -f ./docker/docker-compose.yml up -d

# 사용하지 않는 불필요한 이미지 삭제 -> 현재 컨테이너가 물고 있는 이미지는 삭제되지 않습니다.
docker rmi -f $(docker images -f "dangling=true" -q) || true

전 포스터와 비슷하지만 기존에 Spring service 이미지만 컨테이너로 실행하는 명령어 대신
docker-compose.yml를 실행하는 명령어를 통해 Spring service 컨테이너, Redis 컨테이너가 함께 실행되고 연계될수 있도록 하였다.


4. Jenkins pipeline 수정

Jenkins의 Pipeline의 대부분은 전 포스터에 구현한것과 비슷하다

차이점은 마지막 ssh를 이용한 운영서버로 send하는 부분의 step에 수정된 deploy.sh을 실행시키도록 하였다.
또한 docker-compose.yml파일을 프로젝트 최상의 디렉토리에 정의하였기 때문에 운영서버로 해당 docker-compose.yml파일을 전달하도록 수정하였다.

pipeline {
       ...
    
       stage('Execute cotanier'){
           agent any
           steps{
                sshPublisher(
                publishers: [
                    sshPublisherDesc(
                    configName: 'deploy_server', 
                    transfers: [
                        sshTransfer(cleanRemote: false, 
                        excludes: '', 
                        execCommand: 
                        '''
                        echo [dockerhub password] | docker login -u [dockerhub 계정] --password-stdin 
                        sh docker/docker_deploy_edit.sh  //수정
                        ''', 
                        execTimeout: 120000, 
                        flatten: false, 
                        makeEmptyDirs: false, 
                        noDefaultExcludes: false, 
                        patternSeparator: '[, ]+', 
                        remoteDirectory: 'docker/', //수정
                        remoteDirectorySDF: false, 
                        removePrefix: '', 
                        sourceFiles: 'docker-compose.yml' //수정
                        )], 
                    usePromotionTimestamp: false, 
                    useWorkspaceInPromotion: false, 
                    verbose: false)]
            	)
           }
       }
    }
}

마치며🤣
나름대로 공부하여 Redis Issue문제를 해결하였다.
기초를 공부하고 많은 자료를 찾아봤지만 나의 구현방식과 비슷한 방식이 나오지 않아서 나름대로 응용하여 구현해보았다.

그러다 보니 설계한 방식대로 잘 흘러갔지만 CI/CD가 되는것에는 상관없지만 약간의 문제가 발생하였다.
jenkins가 빌드가 되고 마지막 단계에 아래와 같은 약간의 문제가 생겨 안전하지 않게 종료가 되었다.

찾아보았지만 sh파일의 권한이 없어서 나오는 문제라고 하였는데 파일 권한을 모두 사> 용자가 실행할수 있게 바꾸었고 하였지만 해결되지 않았다.ㅠㅠㅠ
혹시나 아시는 사람이 있으면 댓글달아주시기 바랍니다.ㅠㅠㅠ

profile
백엔드 개발자를 꿈꾸며 기록중💻

0개의 댓글