1. 서론
Docker를 사용하려면 Docker를 설치해야 한다. 설치되는 곳은 우리의 PC일수도 있고, AWS와 같은 클라우드 서비스일 수도 있다. 우리가 어떤 어플리케이션을 배포한다고 가정하면 어플리케이션이 실제로 존재하는 서버는 우리의 PC가 될 수도 있고, 클라우드 서비스를 이용해 서버를 구축할 수도 있다. 즉, Docker를 활용해 우리의 어플리케이션을 배포하기 위해서는 서버를 어디에서 어떻게 구축할지부터 결정해야 한다.
필자는 AWS EC2 서비스를 활용했다. AWS 계정을 새로 생성하면 1년 동안 일부 AWS 서비스를 무료로 이용할 수 있는데, 이를 프리티어라고 한다. 프리티어인 경우 매월 정해진 최대 사용량을 초과하지 않는다면 아예 무료이고, 성능이 아쉽다면 딱 한단계 높은 인스턴스로 매우 저렴하게 서버를 돌릴 수 있다. 필자는 백엔드(Spring boot) 서버로는 t2.micro 인스턴스를, 프론트엔드(React) 서버로는 t2.medium 인스턴스를 활용했다. t2.micro가 프리티어이다. 쉽게 말하면 AWS로부터 컴퓨터를 할당받아 우리의 어플리케이션 배포를 위한 서버로 활용했다는 뜻이다.
2. 왜 클라우드 서비스를 선택했는가?
그렇다면 우리의 노트북등의 개인 PC를 서버로 활용할 수는 없을까? 당연히 가능하다. 외부에서 우리의 PC로 접근할 수 있도록 포트포워딩 등의 작업을 한다면 충분히 우리의 개인 PC를 서버로 활용할 수 있다. 서버로 활용할 목적이라면 우리의 개인 PC이든 클라우드 서비스에서 할당받은 컴퓨터이든 간에 본질적으로는 다르지 않다는 뜻이다. 하지만 관리 및 유지 보수, 확장 측면에서는 클라우드 서비스가 차별화되는 장점을 가지고 있다. 클라우드 서비스가 제공하는 클라우드 컴퓨팅은 용량 계획을 탄력적으로 할 수 있게 하며, 비용을 절감시키고 조직의 민첩성에 긍정적인 영향을 미친다. 따라서 클라우드 컴퓨팅 기술은 어떤 비즈니스를 운영하는데 있어 효율적인 방안을 제시해줄 수 있다.
클라우드 컴퓨팅의 장점은 다음과 같다.
- 투자 절감 : 자회사 장비 투자에 비용을 지불하는 대신에 클라우드 서비스를 사용하면 필요시에만 컴퓨팅 자원을 사용하고 그만큼만 사용료를 지급하기 때문에 자금을 효율적으로 사용할 수 있다.
- IT 자원 확장성 : 요구에 변동 상황이 발생했을 시에 자유롭게 IT 자원을 확장하거나 축소할 수 있다.
- 가용성과 신뢰성 증대 : 서비스 중단은 기업 이익에 엄청난 악영향을 미친다. 클라우드 컴퓨팅은 IT 자원 가상화를 통해 서비스가 사용하는 자원들을 다중화시켜 무중단 서비스를 제공하거나 쉽게 업그레이드시킬 수 있게 하여 이를 방지한다.
물론 공중 인터넷 망에 노출되기 때문에 보안 취약성이 증가한다는 단점과, 클라우드 제공자마다 다른 환경의 인프라를 제공한다는 제한된 이식성의 문제가 존재한다. 하지만 클라우드 컴퓨팅 기술은 상술한 장점을 가지고 IT 산업에 있어 상당한 중요성을 가지는 기술이기 때문에 프로젝트를 진행하며 직접 경험해보고 다루고 싶다고 생각했다. 그러므로 필자는 서버 구축에 AWS EC2 서비스를 사용하게 되었다.
3. AWS EC2 인스턴스 시작
EC2(Elastic Compute Cloud)란 아마존에서 제공하는 클라우드 컴퓨팅 서비스로, 아마존이 사용자들에게 독립된 컴퓨터를 임대해주는 서비스이다. 이를 통해 사용자는 가상화된 서버를 구축하고 빠르게 어플리케이션을 개발 및 배포할 수 있으며, 자신의 목적에 맞게 서버의 여러가지 성능이나 운영체제 등을 선택하여 유연하게 클라우드 컴퓨팅 자원을 할당받아 사용할 수 있다.
인스턴스를 생성하는 화면으로 넘어가면, 다음과 같이 인스턴스의 이름을 정할 수 있는 블럭부터 시작할 수 있다. 자신만의 인스턴스 이름을 정하면 된다.
AMI(Amazon Machine Image)를 선택할 수 있다. 쉽게 말하면, 우리가 할당받을 컴퓨터의 OS를 선택하는 것이다. Linux 환경에서는 다양한 오픈소스를 무료로 사용할 수 있다는 장점이 있으므로 배포 서버의 OS로 Ubuntu를 선택했다.
각 인스턴스 유형은 성능과 크기, 최적화된 부분이 다르기에 이에 맞춰 적절하게 선택해야 한다.
해당 블로그에 각 인스턴스 유형 별 특징에 대해 정리가 잘 돼 있다.
필자는 백엔드(Spring boot)의 경우 프리티어인 t2.micro 인스턴스를 선택했다.
SSH 프로토콜로 인스턴스에 접속하는 경우, 이 키페어를 가지고 있어야 해당 인스턴스에 접근 가능하다. 보안을 위해서도 인스턴스에 대한 키페어 생성은 권장된다. 키페어 생성을 통해 다운로드한 키 파일은 다시 다운로드할 수 없기 때문에 꼭 안전한 위치에 자신의 키파일을 잘 저장해두자. 후일 Jenkins등의 툴로 인스턴스에 원격 접속할 경우가 생기기 때문에 꼭 잘 저장해두자.
보안그룹은 방화벽이라고 생각하면 된다. 인스턴스는 터미널을 통해 접속하기 때문에 SSH 22번 포트가 기본 값으로 설정 돼 있다. 이를 통해 외부에서 들어오는 트래픽(인바운드)를 사용자 입맛에 맞게 허용할 수 있다. 다시 말해, 서버 내에 어플리케이션을 생성하고 이를 외부에서 접근할 수 있게 하고자 한다면, 해당 어플리케이션에 맞는 포트를 개방시켜야 하고, 이를 보안그룹 설정을 통해 설정할 수 있다는 것이다. 보안그룹은 인스턴스 생성 후 서버 내에 여러 어플리케이션을 올리며 커스터마이징할 수 있기 때문에, 일단은 이대로 두어도 된다.
프리티어 기준으로 30GiB까지 무료이다. 만약 본인이 한 계정에서 여러 인스턴스를 생성할 계획이라면, 30GiB를 잘 분배하면 된다. 확장은 쉽지만 축소는 굉장히 까다롭고 번거로운 작업이기 때문에, 조금은 신중하는 편이 후일을 위해 좋다.
이제 인스턴스 시작을 누르면 인스턴스가 생성된다.
4. EC2 스왑 메모리 설정
본격적으로 배포 서버를 구축하기 전, 프리티어 서버를 사용한다면 메모리가 굉장히 부족하다.(프리티어인 t2.micro의 RAM은 1GiB임.) 따라서 Jenkins등의 툴을 함께 사용한다면 메모리 부족 현상(멈춤 현상 등)에 골이 아파질 수 있다. 따라서 스왑 메모리를 통해 프리티어의 부족한 램 용량을 보완하고 시작하는 것을 권장한다.
스왑 메모리는 디스크 용량(쉽게 말해 저장소) 일부를 메모리로 사용하는 기법이다. 물론 실제 RAM보다 성능은 떨어지고 비효율적인 방식이지만, 프리티어에서는 이 정도로도 메모리 부족 현상을 꽤나 완화시킬 수 있다.
스왑 메모리를 설정하고자 하는 EC2 인스턴스에 접속한다.
스왑 파일을 생성한다.
sudo dd if=/dev/zero of=/swapfile bs=128M count=16
- dd : 블록 단위로 파일을 복사하거나 변환시킬 수 있는 명령어
- if : 지정한 파일을 입력 대상으로 설정
- of : 지정한 파일을 출력 대상으로 설정
- bs : 한 번에 변환 가능한 바이트 크기
- count : 지정한 블록 수만큼 복사
/dev/zero 파일은 읽기 요청 시 요청한 만큼의 널 문자(0x00)을 반환하는 특수 파일이다. 스왑 시 이를 입력 파일로 두는 이유는 dd 명령어를 통해 블록 크기를 지정하고 새로운 파티션을 생성할 때, 해당 파티션에 널문자(0x00)을 채워 넣기 위함이다. 즉, 블록 크기만큼 데이터 스토리지를 초기화하기 위한 문자 스트림을 제공하는 파일이다.
일반적으로 스왑 메모리는 RAM 메모리의 2배 용량이 권장되므로, bs x count = 128M x 16 = 2GB인 swapfile을 생성한다. 만약 4GB를 생성한다면 count를 2배하면 된다.
swapfile에 대한 권한을 설정한다.
sudo chmod 600 /swapfile
- chmod : 파일 사용 권한을 설정하는 명령어이다. 600에서 각각의 자릿수를 8진수로 변환하면 (110 000 000)이다. 첫번째 자리수(6)는 파일을 소유한 사용자(이 경우 root)이며, 두번째 자릿수는 특정 그룹에 소속된 사용자, 세번째는 그 외 사용자이다. 첫번째의 경우 110은 순서대로 r(읽기), w(쓰기), x(실행)에 대한 권한 부여를 나타낸다. 즉, root 사용자는 r과 w가 가능하다는 이야기이다. 나머지의 경우도 같은 논리로 권한을 적용시킬 수 있다. 즉 /swapfile은 소유자(root)에게 읽고 쓸 수 있는 권한을 부여한다.
스왑 공간을 생성한다.
sudo mkswap /swapfile
- mkswap : 리눅스의 스왑 영역을 지정하는 명령어이다. 뒤 인자에는 파티션이나 파일이 올 수 있다. 우리가 만든 스왑 파일을 스왑 파일 시스템으로 지정하는 것이다.
스왑 영역을 활성화시킨다.
sudo swapon /swapfile
- swapon : 스왑 영역 활성화 및 스왑 영역 확인에 사용되는 명령어이다. 우리가 생성한 swapfile을 활성화시켜 스왑 영역에 해당 파일을 추가해 스왑 파일이 즉시 사용될 수 있도록 만든다.
sudo swapon -s
# Result
Filename Type Size Used Priority
/swapfile file 4194300 889600 -2
sudo swapon -s 명령어로 우리가 지정한 swapfile이 제대로 스왑 영역에 추가됐는지 확인할 수 있다.
스왑은 시스템의 전원이 종료될 때 해제된다. 즉, 시스템 재부팅 시 파일시스템 테이블에 미리 등록되어 있지 않다면 자동으로 활성화되지 않는다. 따라서 이대로 설정을 마칠 경우. 인스턴스를 중지하고 시작하는 과정마다 우리가 스왑을 계속해서 지정해줘야 하는 번거로움이 생긴다. 이를 방지하기 위해 시스템 부팅마다 자동으로 활성화되도록 파일 시스템을 수정한다.(필자는 nano 편집기를 사용한다.)
sudo nano /etc/fstab
# fstab
LABEL=cloudimg-rootfs / ext4 discard,errors=remount-ro 0 1
LABEL=UEFI /boot/efi vfat umask=0077 0 1
/swapfile swap swap defaults 0 0
맨 아래에 위와 같이 /swapfile swap swap defaults 0 0을 추가한다.
/etc/fstab은 파일 시스템 정보를 저장하고, 리눅스 시스템 부팅 시 마운트 정보를 저장한다. 이 파일에 아래와 같이 작성하여 부팅 시 자동으로 적용될 수 있도록 할 수 있는 것이다.
<파일 시스템 장치> <마운트 포인트> <파일 시스템 종류> <옵션> <덤프> <파일 체크 옵션>
해당 블로그에서 이에 대한 자세한 내용을 확인할 수 있다.
스왑 메모리 적용을 확인한다.
free -h
# Result
total used free shared buff/cache available
Mem: 957Mi 727Mi 77Mi 0.0Ki 153Mi 80Mi
Swap: 4.0Gi 851Mi 3.2Gi
위와 같이 할당된 스왑 메모리를 확인할 수 있다. 필자는 4GB을 할당하였으나, 언급한 바와 같이 RAM의 두 배를 할당하는 것이 가장 권장된다.
5. Docker 설치
이제 배포 서버인 우분투에 Docker를 설치해보자.
먼저 우분투 시스템 패키지 업데이트를 실시한다.
sudo apt-get update
- apt-get : 우분투에서 패키지 설치와 관련된 명령어이다. apt 또는 apt-get을 사용하여 패키지를 설치할 수 있는데, 둘 중 어느 것을 써도 내부 동작의 차이는 거의 없으나 apt-get이 더 많은 옵션을 가지고 더 많은 기능을 제공해준다는 특징이 있다. apt는 자주 사용하는 옵션을 추출해서 사용자의 편의성면에서 유리하고, 가독성 좋은 출력이 장점이다. 결론적으로는 대부분의 경우 apt, apt-get 무엇을 쓰든 상관없다.
- update : 설치된 패키지 "정보"를 최신화한다. 현재 설치된 패키지들을 실제로 업데이트하는 것이 아닌, 패키지의 source와 비교하여 업데이트 가능 목록을 받아온다고 생각하면 편하다. 실제 설치된 패키지들의 업데이트는 update 명령어로 최신화 후 sudo apt-get upgrade 명령어를 통해 이루어진다.
Docker 다운로드를 위해 필요한 패키지들을 설치한다.
sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
- install : 뒤에 오는 인자에 해당하는 패키지(들)를 설치한다.
- apt-transport-https : 패키지 관리자가 https 프로토콜을 통해 데이터 및 패키지에 접근할 수 있도록 만드는 패키지이다.
- ca-certificates : 인증서 기반의 SSL 통신을 가능하게 해주는 패키지이다. 사설 저장소를 이용할 때 디지털 인증서가 필요한 경우가 있는데, 최신화된 SSL 인증서의 pem 파일을 가지고 인증 절차를 진행해준다.
- curl : URL 기반으로 직접 서버에 http request를 보내고 response를 확인할 수 있게한다. 이를 통해 특정 웹사이트에서 데이터를 다운받을 수도 있다. 다운받을 수 있게하는 패키지에는 wget도 있으나, curl은 더 다양한 프로토콜과 기능, 좋은 이식성을 가지고 있다.
- gnupg-agent : 해당 패키지는 Daemon 프로그램이며(백그라운드 프로그램), GPG 비밀 키를 메모리에 저장하고, GPG 프로세스가 진행될 시 보관된 GPG 키를 제공하여 프로세스를 진행시킨다. *GPG 키는 디지털 서명, 암호화, 소프트웨어 패키지의 무결성 검증 등에 사용된다.
- software-properties-common : PPA를 추가하거나 제거할 때 사용하는 패키지이다. *PPA(Personal Package Archive)는 말 그대로 개인 패키지 저장소로, 우분투 공식 저장소에 없는 패키지를 받을 때 사용한다.
리눅스 패키지 관리 툴은 특정 패키지 설치 전 해당 패키지의 유효 여부를 검증하는데, 이를 GPG 키로 검증한다. Docker를 설치하기 위해서는 GPG 키가 필요하므로, Docker의 공식 GPG 키를 apt 툴에 추가해야한다.
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
- -f, --fail : HTTP 요청에 대해 실패했을 때, 결과를 출력 하지 않는다.
- -s, --silent : curl의 진행 과정을 출력하지 않는다.
- -S, --show-error : -s 옵션이 활성화 됐을 때, 에러가 발생한 경우는 해당 내용을 출력한다.
- -L, --location : HTTP 응답이 redirect일 경우(HTTP 301 or 302), curl 명령어를 한번 더 수행하여 변경된 URL로 redirect한다.
- https://download.docker.com/linux/ubuntu/gpg : Docker의 공식 GPG 키가 존재하는 경로이다.
- | : 리눅스의 파이프이다. 여러 개의 명령어를 실행할 때, 이전 명령어의 출력 값을 다음 명령어의 입력 값으로 사용할 수 있게 한다. 앞 명령어의 출력 값이 뒤 명령어의 인자로 들어가게 된다. 복수 명령어 연결 또한 가능하다.
- sudo apt-key add - : apt-key는 apt가 패키지를 인증할 때 사용하는 키 목록을 관리하는 패키지이다. add 명령어로 키 리스트에 새로운 키를 추가한다. -(hyphen)은 표준 입력(stdin)으로 인자값을 받는다는 의미이다. 즉, curl 명령어로 응답을 받은 GPG 키가 출력(stdout)되면, 이 내용이 - 위치에 들어와 새로운 키가 추가되는 것이다.
이제 apt로 Docker를 다운받기 위해 Docker의 공식 apt 저장소를 추가해야 한다.
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
- add-apt-repository : 뒤 명령 인자로 값을 주면 명령 인자에 해당하는 저장소 이름을 가진 PPA에 대한 경로가 apt 리스트에 추가된다. 따라서 해당하는 패키지를 apt로 다운로드 받을 수 있게 된다.
- lsb_release : 우분투 버전을 확인하기 위한 명령어이다. -c(--codename) 옵션은 현재 설치된 우분투의 code name을 출력하게 한다. -s(--short) 옵션은 출력을 단순화시킨다. 이를 조합해서(-cs) 쓰게 되면 딱 code name에 해당하는 문자열 값만 출력하게 된다. 따라서 lsb_release -cs의 실행 결과는 우분투의 버전에 맞는 code name이며, 이 명령어의 결과를 문자열로 대입하기 위해 $()으로 감싸면 현재 버전에 맞는 code name이 문자열 내에 대입할 수 있다. 이로 인해 우리 환경에 맞는 Docker 저장소를 apt 리스트에 추가할 수 있다.
apt 저장소 리스트에 새로운 저장소가 추가되었으므로 최신 Docker를 설치하기 위해 다시 시스템 패키지를 업데이트하자.
sudo apt-get update
이제 Docker를 설치한다.
sudo apt-get install docker-ce docker-ce-cli containerd.io
- docker-ce : docker 서버 역할을 하는 패키지이다. 무료로 제공되는 CE(Community Edition)이다. 소규모 프로젝트에 적합하다. 대조적으로 유료로 제공되는 기업용 솔루션인 EE(Enterprise Edition)이 존재한다.
- docker-ce-cli : docker 클라이언트 명령어 정보가 포함된 패키지이다.
- containerd.io : LXC를 사용하기 위한 컨테이너 패키지이다. 업계 표준을 따른다. *LXC는 리눅스 컨테이너스이다. 커널 컨테이널 기술을 의미한다. docker는 이 기술을 기반으로 만들어졌으며, LXC에 전적으로 의존하지는 않으나, LXC 옵션 등을 사용할 수 있다.
설치가 정상적으로 완료되었다면, Docker가 잘 구동되고 있는지 확인해보자.
sudo systemctl status docker
# Result
● docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2024-11-22 09:29:31 UTC; 7h ago
...
References
- https://velog.io/@kyj311/AWS-EC2-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0
- https://diary-developer.tistory.com/32
- https://jungtak.tistory.com/305
- https://itdexter.tistory.com/311
- https://velog.io/@osk3856/Docker-Ubuntu-22.04-Docker-Installation
- https://velog.io/@akfvh/sudoApt-vduqb7mk
- https://roseline124.github.io/kuberdocker/2019/07/17/docker-study02.html
- https://askubuntu.com/questions/857476/what-is-the-use-purpose-of-the-ca-certificates-package
'Docker' 카테고리의 다른 글
[Docker] Spring boot App 배포 (4) - 서버에 배포하기 (0) | 2024.11.28 |
---|---|
[Docker] Spring boot App 배포 (3) - Web App 구동 및 빌드 (1) | 2024.11.26 |
[Docker] Spring boot App 배포 (1) - Docker 기본 (1) | 2024.11.19 |