[AWS] 개발용 RDS 구축하기 (5)

스윗포테이토·2022년 12월 8일
1

지난 글에서는 로컬에서 ssh 터널링을 통해 RDS에 접근하는 방법에 대해 알아보았다. 그러나 나는 도커를 사용중이기 때문에, 컨테이너 내부에서 호스트(내 PC)의 localhost에 접근하기 위한 방법이 필요했다.

1. host.docker.internal

도커에서는 자체적으로 호스트의 localhost를 접근할 수 있도록 host.docker.internal 도메인을 제공한다. 따라서 로컬에서 ssh 터널링을 수행한 후에 컨테이너에서는 localhost 대신 host.docker.internal을 사용하면 된다.

2. 백엔드 컨테이너에서 ssh tunnelling 수행하기

로컬에서 매번 ssh 터널링을 해주기가 조금 번거롭긴 하다. 게다가 다른 팀원들은 윈도우를 쓰고 있기 때문에 혹시 모를 환경 문제를 막고 싶었다. 따라서 컨테이너에서 직접 띄우는 방법을 시도해보았다. 기존에 있던 백엔드 컨테이너에서 백그라운드로 ssh 터널링을 수행하면 해당 컨테이너에서는 localhost로 접근이 가능하게 된다.

실행 중인 컨테이너에 접속해 기존 명령어에 -fN 옵션을 추가하면 ssh를 백그라운드로 연결할 수 있다.

<컨테이너 접속>

docker exec -it <container id> /bin/bash

이미지에 따라 bash를 찾을 수 없다고 오류가 날 수 있다. /bin/sh로 바꿔주면 된다.

<ssh 터널링>

ssh -fN -4 -i "${SSH_PEM_KEY}" -L ${MYSQL_PORT}:${RDS_HOST}:${MYSQL_PORT} ${SSH_USER}@${SSH_HOST}

그러나 이 과정을 매번 수동으로 할 수 없다. Dockerfile에서 RUN 명령어를 통해 실행하려고 했으나, RDS 접속 주소, EC2 주소, username 등 민감한 정보를 github에 올라가게 둘 수 없어서 환경변수를 이용하기 위해 쉘스크립트를 작성해 CMD로 실행하도록 했다.

  1. dockerfile 수정

    CMD ["./entrypoint.sh"]
  2. 환경 변수 작성
    .env파일에 환경변수를 작성하고, docker-compose.yml에서 env_file로 등록한다.

      backend:
        container_name: backend
        build:
          context: ./server
          dockerfile: Dockerfile.dev
        env_file: ./server/.env
        ...
  3. fingerprint 등록
    처음 ssh 접속을 할 때 fingerprint를 허용해야 한다. 원래라면 직접 yes를 쳐야 하는데, 직접 터미널에 입력을 할 수 없는 상황이니 미리 known_hosts에 등록해두었다.

    mkdir -p ~/.ssh
    ssh-keyscan -H ${SSH_HOST} > ~/.ssh/known_hosts
  4. pem key 권한 설정
    이후 pem key의 권한이 너무 높으면 문제가 되는 경우도 있기 때문에 권한을 낮춰주었다.

    chmod 400 ${SSH_PEM_KEY}

  • 전체 쉘 스크립트 (entrypoint.sh)

    #!/bin/bash
    
    #shell script for ssh port forwarding
    mkdir -p ~/.ssh
    ssh-keyscan -H ${SSH_HOST} > ~/.ssh/known_hosts
    chmod 400 ${SSH_PEM_KEY}
    ssh -fN -4 -i "${SSH_PEM_KEY}" -L ${MYSQL_PORT}:${RDS_HOST}:${MYSQL_PORT} ${SSH_USER}@${SSH_HOST}
    
    # 기존 백엔드 코드
    npx nodemon -L main.js

이렇게 설정했을 때도 문제가 있다. 바로 SSH 연결이 일정 시간이 지나면 끊어진다는 것이다. 아마 timeout 설정과 관련이 있을 것 같은데, 일정 주기로 통신 패킷을 보내는 방식을 시도해봐야 할 것 같다.

reference

Docker Container 내부에서 Host로 접근하는 방법
Automatically Accept SSH Fingerprint

profile
나의 삽질이 미래의 누군가를 구할 수 있다면...

0개의 댓글