진행 중인 PoC에서 SSH 접속 방식을 테스트해야 했다. 그런데 공식 ubuntu Docker 이미지에는 SSH 서버(openssh-server)가 들어 있지 않다. 컨테이너는 bash 하나만 띄운 채로 시작하니 22번 포트에서 기다리는 프로세스가 없다.

이 글에서는 컨테이너에 SSH 서버를 직접 깔고 로컬에서 ssh로 들어가기까지를 정리한다.

테스트용으로 보안은 일부러 낮췄다

먼저 범위를 분명히 해 둔다. 여기서는 root 계정에 비밀번호를 걸고 그 비밀번호로 접속한다. 접속 방식이 되는지만 확인하려는 테스트라서 그렇다. 실제로 쓸 환경이라면 별도 계정을 만들고 공개키 인증을 쓰는 게 맞다.

접속 주소도 컨테이너 IP가 아니라 localhost다. 컨테이너 IP로는 SSH 접속이 되지 않는다. 왜 안 되는지는 「Mac에서 컨테이너 IP로 접속이 안 되는 이유」에서 따로 다뤘다.

링크: https://jaylab.blog/docker-container-network-arch/

컨테이너를 띄울 때 22번 포트를 미리 연다

Ubuntu 컨테이너를 실행하면서 바로 bash로 들어간다.

docker run -it --name {컨테이너 이름} -p 2222:22 ubuntu:latest bash
  • -p 2222:22: 로컬 포트 2222를 컨테이너의 22번(SSH) 포트로 포트포워딩

포트 매핑은 컨테이너를 만들 때만 정할 수 있다. 나중에 SSH를 쓸 생각이라면 이 단계에서 열어 둬야 한다.

컨테이너 안에서 sshd를 깔고 root 로그인을 연다

컨테이너 안에서 SSH 서버를 설치한다.

apt update
apt install -y openssh-server

설치만 해서는 비밀번호로 root에 들어갈 수 없다. sshd_config의 기본값인 PermitRootLogin prohibit-password가 root 로그인 자체는 허용하되 비밀번호 방식은 막아 두기 때문이다. 이 줄을 yes로 바꾸고 root 비밀번호를 정한 뒤 SSH 서버를 띄운다.

echo "root:DockerPass123" | chpasswd   # root 비밀번호 설정

# SSH 설정파일에서 root 비밀번호 로그인 금지 → 허용으로 바꾸는 설정
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
service ssh start   # SSH 서버 구동

로컬에서 2222번으로 붙는다

컨테이너 쉘은 그대로 두고 새 터미널을 열어 로컬에서 접속한다.

ssh root@localhost -p 2222

비밀번호는 앞에서 정한 DockerPass123이다. 로컬 2222번으로 들어온 연결이 컨테이너 22번으로 넘어가고, 거기서 기다리던 sshd가 받는다.

매번 sshd를 켜기 싫으면 Dockerfile로 굳힌다

위 방식대로면 컨테이너를 다시 띄울 때마다 service ssh start를 또 쳐야 한다. 컨테이너가 뜰 때마다 sshd가 돌게 하려면 Dockerfile에 CMD ["/usr/sbin/sshd", "-D"]를 적는다. -D 옵션을 주면 sshd가 데몬으로 떨어져 나가지 않고 포그라운드에 남아 컨테이너의 메인 프로세스 역할을 한다.

# Dockerfile 예시
FROM ubuntu:latest
RUN mkdir /run/sshd
RUN apt update && apt install -y openssh-server
RUN echo "root:DockerPass123" | chpasswd
RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
CMD ["/usr/sbin/sshd", "-D"]

공식 Ubuntu 이미지 대신 SSH가 이미 들어 있는 이미지를 쓰는 방법도 있다.

정리

컨테이너는 서버가 아니라 프로세스 하나라서, SSH가 필요하면 sshd를 직접 깔고 띄워야 한다. 포트는 컨테이너를 만들 때 열고, root 비밀번호 로그인은 테스트에서만 쓴다.

참고자료