Docker를 사용하는 이유
이식성
특정 프로그램을 다른 곳으로 쉽게 옮겨서 설치 및 실행할 수 있는 특성
기타 장점
- 매번 귀찮은 설치 과정을 일일이 거치지 않아도 됨
- 항상 일관되게 프로그램을 설치 가능(버전, 환경 설정, 옵션, 운영 체제 등)
- 각 프로그램이 독립적인 환경에서 실행되기 때문에 프로그램 간에 서로 충돌이 일어나지 않음
IP와 Port
IP
IP(Internet Protocol Address)
네트워크 상의 장치들을 식별하기 위한 고유한 주소
IPv4(32비트), IPv6(128비트)
ex) 172.30.1.96
Port
Port Number
한 컴퓨터 내에서 실행되고 있는 특정 프로그램의 주소
특정 IP 주소 내에서 실행되는 특정 서비스를 식별하는 데 사용. 0 ~ 65535 사이의 숫자로 구성
ex) 13.250.15.132:3000 → :3000 부분이 포트 번호를 의미
외부에서 특정 서버와 통신할 때는 IP 주소와 서버가 실행되고 있는 포트 번호까지 알고 있어야 함
브라우저 창에 포트 번호를 입력하지 않는 이유
- 주소창에 도메인 주소를 입력해서 엔터를 누르면 브라우저는 기본적으로 80번 포트로 통신을 보내게 설정되어 있음
→ naver.com을 입력하면 자동으로 80번 포트로 통신을 보냄 - 만약 80번 포트가 아닌 3000번 포트로 통신을 하고 싶다면?
→ naver.com:3000과 같이 주소창에 입력하면 됨
잘 알려진 포트(well-known port)
0 ~ 1023번까지의 포트 번호는 주요 통신을 위한 규약에 따라 이미 정해져 있다. 이렇게 규약을 통해 역할이 정해져 있는 포트 번호를 보고 잘 알려진 포트라고 부른다.
- 22(SSH, Secure Shell Protocol): 원격 접속을 위한 포트 번호 → EC2 인스턴스에 연결할 때 22번 포트 사용
- 80(HTTP): HTTP로 통신을 할 때 사용
- 443(HTTPS): HTTPS로 통신을 할 때 사용
규약은 규약일 뿐 꼭 지키지 않아도 된다. 예를 들어 특정 서버와 HTTP 통신을 할 때 80번 포트를 쓰지 않고 3000번 포트나 8080번 포트를 사용해도 상관 없다.
도커(Docker), 컨테이너(Container), 이미지(Image)
도커(Docker)
컨테이너를 사용하여 각각의 프로그램을 분리된 환경에서 실행 및 관리할 수 있는 툴
컨테이너(Container)
윈도우 환경을 사용해보면 하나의 컴퓨터에 여러 사용자로 나눠서 사용할 수 있게끔 구성되어 있다. 각 사용자의 환경에 들어가보면 독립적으로 구성되어 있어서 필요한 프로그램을 각 사용자 환경에 각각 설치해주어야 한다. 컨테이너도 이와 비슷한 개념이다.
하나의 컴퓨터 환경 내에서 독립적인 컴퓨터 환경을 구성해서, 각 환경에 프로그램을 별도로 설치할 수 있게 만든 개념이다. 하나의 컴퓨터 환경 내에서 여러 개의 미니 컴퓨터 환경을 구성할 수 있는 형태이다. 여기서 얘기하는 미니 컴퓨터를 보고 Docker에서는 Container라고 부른다.
컨테이너의 독립성
컨테이너는 독립적인 컴퓨터 환경이다.
- 디스크(저장 공간): 각 컨테이너마다 서로 각자의 저장 공간을 가지고 있다. 일반적으로 A 컨테이너 내부에서 B 컨테이너 내부에 있는 파일에 접근할 수 없다.
- 네트워크(IP, Port): 각 컨테이너마다 고유의 네트워크를 가지고 있다. 컨테이너는 각자의 IP 주소를 가지고 있다.
이미지(Image)
닌텐도와 같은 게임기를 보면 여러가지 칩을 꽂아서 다양한 게임을 즐길 수 있게 되어 있다. Docker에서는 닌텐도의 칩과 같은 역할을 하는 개념이 이미지이다.
예시로 MySQL 서버를 이미지로 만들었다면, 이 이미지를 Docker로 실행시키는 순간 MySQL 서버가 컨테이너 환경에서 실행된다. MySQL을 일일이 설치할 필요없이 MySQL 데이터베이스를 사용할 수 있게 된다.
이미지는 프로그램을 실행하는 데 필요한 설치 과정, 설정, 버전 정보 등을 포함하고 있다. 즉, 프로그램을 실행하는 데 필요한 모든 것을 포함하고 있다.
Docker로 Nginx 설치 및 실행해보기
Nginx
웹서버(HTML 웹 페이지를 렌더링시키는 역할), 로드 밸런싱, 리버스 프록시 등의 기능을 보유
Nginx 이미지 다운로드
docker pull nginx
다운로드된 이미지 확인
docker image ls
이미지를 컨테이너에 올려 Nginx 서버 실행
docker run --name webserverr -d -p 80:80 nginx
Nginx 서버가 잘 실행되는지 확인
실행되고 있는 모든 컨테이너 상태 확인
docker ps
특정 컨테이너 정지
docker stop webserver
특정 컨테이너 정지 + 삭제
docker rm -f webserver
이미지(Image) 다운로드
최신 버전(latest) 이미지 다운로드
docker pull 이미지명
docker pull nginx
이미지를 다운로드할 때는 Dockerhub라는 곳에서 이미지를 다운 받는다.
특정 버전 이미지 다운로드
docker pull 이미지명:태그명
docker pull nginx:stable-perl
특정 버전을 나타내는 이름을 태그명이라고 한다. 태그명은 dockerhub에서 확인할 수 있다.
이미지(Image) 조회 / 삭제
다운받은 모든 이미지 조회
docker image ls
- ls: list
- REPOSITORY: 이미지 이름(이미지 명)
- TAG: 이미지 태그명
- IMAGE ID: 이미지 ID
- CREATED: 이미지가 생성된 날짜(다운받은 날짜 x)
- SIZE: 이미지 크기
이미지 삭제
특정 이미지 삭제
docker image rm [이미지 ID 또는 이미지명]
- 이미지 ID를 입력할 때 전체 ID를 다 입력하지 않고 ID의 일부만 입력 가능
(입력한 ID의 일부를 가진 이미지가 단 1개일 경우만) - 컨테이너에서 사용하고 있지 않은 이미지만 삭제 가능
중지된 컨테이너에서 사용하고 있는 이미지 강제 삭제
docker image rm -f [이미지 ID 또는 이미지명]
- 실행 중인 컨테이너에서 사용하고 있는 이미지는 강제로 삭제 불가
전체 이미지 삭제
컨테이너에서 사용하고 있지 않은 이미지만 전체 삭제
docker image rm $(docker images -q)
컨테이너에서 사용하고 있는 이미지를 포함해서 전체 이미지 삭제
docker image rm -f $(docker images -q)
- docker images -q
- 시스템에 있는 모든 이미지의 ID 반환
- -q : quite를 의미, 상세 정보 대신 각 이미지의 고유한 ID만 표시하도록 지시
컨테이너(Container) 생성/실행 - 1
컨테이너 생성
이미지를 바탕으로 컨테이너를 생성한다(이 때, 컨테이너를 실행시키지는 않음).
docker create 이미지명[:태그명]
docker create nginx
- 로컬 환경에 다운받은 이미지가 없다면 Dockerhub로부터 이미지를 다운(docker pull)받아서 컨테이너를 생성함
모든 컨테이너 조회
docker ps -a
컨테이너 실행
정지되어 있는 컨테이너를 실행
docker start 컨테이너명[또는 컨테이너 ID]
실행 중인 컨테이너 조회
docker ps
Nginx 컨테이너 중단 후 삭제
docker ps
docker stop {nginx를 실행시킨 Container ID} #컨테이너 중단
docker rm {nginx를 실행시킨 Container ID} #컨테이너 삭제
docker image rm nginx #Nginx 이미지 삭제
컨테이너(Container) 생성/실행 - 2
컨테이너 생성 + 실행
이미지를 바탕으로 컨테이너를 생성한 뒤, 컨테이너를 실행까지 시킨다.
(처음에 이미지를 바탕으로 컨테이너를 실행시키고 싶을 때, 이 명령어 자주 사용)
docker run 이미지명[:태그명]
docker run nginx
- 위 명령어는 포그라운드(foreground)에서 실행 → 추가적인 명령어 조작 불가, Ctrl + C로 종료 가능
- Dockerhub로부터 새롭게 갱신된 이미지를 다운받고 싶으면 docker pull 명령어 활용
컨테이너를 백그라운드에서 실행시키기
포그라운드(foreground)와 백그라운드(background)
포그라운드(foreground)
- 내가 실행시킨 프로그램의 내용이 화면에서 실행되고 출력되는 상태
- 포그라운드 상태에서는 다른 프로그램 조작 불가
백그라운드(background)
- 내가 실행시킨 프로그램이 컴퓨터 내부적으로 실행되는 상태
- 프로그램이 어떻게 실행되고 있는지에 대한 정보를 화면에서 확인 불가
- 다른 명령어 추가 입력 및 새로운 프로그램 조작 가능
docker run -d 이미지명[:태그명]
docker run -d nginx
Nginx 컨테이너 중단 후 삭제
docker ps # 실행 중인 컨테이너 조회
docker stop {nginx를 실행시킨 Contnainer ID} # 컨테이너 중단
docker rm {nginx를 실행시킨 Contnainer ID} # 컨테이너 삭제
docker image rm nginx # Nginx 이미지 삭제
컨테이너에 이름 붙여서 생성 및 실행
docker run -d --name [컨테이너 이름] 이미지명[:태그명]
docker run -d --name my-web-server nginx
Nginx 컨테이너 중단 후 삭제
docker ps # 실행 중인 컨테이너 조회
docker stop {nginx를 실행시킨 Contnainer ID} # 컨테이너 중단
docker rm {nginx를 실행시킨 Contnainer ID} # 컨테이너 삭제
docker image rm nginx # Nginx 이미지 삭제
호스트의 포트와 컨테이너의 포트 연결
docker run -d -p [호스트 포트]:[컨테이너 포트] 이미지명[:태그명]
docker run -d -p 4000:80 nginx
- docker run -p 4000:80라는 명령어를 입력하게 되면, 도커를 실행하는 호스트의 4000번 포트를 컨테이너의 80번 포트로 연결하도록 설정한다.
- 이유
- 호스트와 컨테이너 간의 네트워크 통신
- Docker 컨테이너는 기본적으로 호스트 시스템과 격리된 네트워크 환경에서 실행됨
- 컨테이너 내부에서 실행되는 서비스에 접근하려면 호스트 시스템의 특정 포트를 컨테이너의 포트에 매핑 필요
- 위와 같이 매핑하면 http://localhost:4000으로 접근하면 컨테이너 내부의 80포트인 nginx가 제공하는 웹 페이지를 볼 수 있음
- 여러 컨테이너 간 포트 충돌 방지
- 같은 호스트에서 여러 컨테이너를 실행할 때 동일한 포트를 사용하면 충돌 발생
- 호스트의 포트를 다르게 지정함으로써 여러 컨테이너가 동일한 서비스를 제공하더라도 서로 간섭없이 동작 가능
- ex) 두 개의 nginx 컨테이너를 각각 호스트의 포트 4000과 5000에 매핑하면 충돌 없이 둘 다 실행 가능
- 보안 및 접근 제어
- 특정 포트를 매핑하여 외부 네트워크에서 접근할 수 있는 범위 제어 가능
- ex) 호스트의 포트 4000을 컨테이너의 포트 80에 매핑하면 외부 네트워크에서 호스트의 포트 4000을 통해서만 컨테이너의 웹 서버 접근 가능
- 불필요한 포트 노출을 막고 보안 강화
- 유연한 서비스 구성
- 다양한 네트워크 구성과 서비스를 유연하게 설정 가능
- 개발 환경과 운영 환경에서 다른 포트를 사용하여 서비스에 접근할 수 있도록 설정 가능
- ex) 개발 환경에서는 호스트의 포트를 4000을 사용, 운영 환경에서는 포트를 80을 사용 가능
- 호스트와 컨테이너 간의 네트워크 통신
컨테이너(Container) 조회 / 중지 / 삭제
컨테이너 조회
실행 중인 컨테이너들만 조회
docker ps
- ps: process status의 약자
모든 컨테이너 조회(작동 중인 컨테이너 + 정지된 컨테이너)
docker ps -a
- -a: all의 약자
컨테이너 중지
docker stop 컨테이너명[또는 컨테이너 ID]
docker kill 컨테이너명[또는 컨테이너 ID]
집에 있는 컴퓨터로 비유하자면,
- stop은 시스템 종료 버튼을 통해 정상적으로 컴퓨터를 종료하는 걸 의미
- kill은 본체 버튼을 눌러 무식하게 종료하는 걸 의미
컨테이너 삭제
중지되어 있는 특정 컨테이너 삭제
docker rm 컨테이너명[또는 컨테이너 ID]
- 실행 중인 컨테이너는 중지한 후에만 삭제 가능
실행되고 있는 특정 컨테이너 삭제
docker rm -f 컨테이너명[또는 컨테이너 ID]
중지되어 있는 모든 컨테이너 삭제
docker rm $(docker ps -qa)
실행되고 있는 모든 컨테이너 삭제
docker rm -f $(docker ps -qa)
컨테이너(Container) 로그 조회
컨테이너를 실행시키고 나서 실행시킨 컨테이너가 잘 실행되고 있는지, 에러가 발생한 건 아닌지 로그를 확인할 수 있어야 한다. 디버깅할 때 필수로 확인해야 하는 것이 로그다. 컨테이너에서 발생한 로그를 확인하는 방법에 대해 알아보자.
컨테이너(Container) 로그 조회
특정 컨테이너의 모든 로그 조회
docker logs [컨테이너 ID 또는 컨테이너명]
docker run -d nginx
docker logs [nginx가 실행되고 있는 컨테이너 ID]
최근 로그 10줄만 조회
docker logs --tail [로그 끝부터 표시할 줄 수] [컨테이너 ID 또는 컨테이너명]
기존 로그 조회 + 생성되는 로그를 실시간으로 보고 싶은 경우
docker logs -f [컨테이너 ID 또는 컨테이너명]
Nginx의 컨테이너에 실시간으로 쌓이는 로그 확인하기
docker run -d -p 80:80 nginx
docker logs -f
- -f: follow의 약어
기존 로그는 조회하지 않기 + 생성되는 로그를 실시간으로 보고 싶은 경우
docker logs --tail 0 -f [컨테이너 ID 또는 컨테이너명]
실행중인 컨테이너 내부에 접속하기(exec-it)
컨테이너 개념 다시 짚어보기
컨테이너는 미니 컴퓨터라고 표현했다. 즉, 호스트 컴퓨터 안에 다른 새로운 컴퓨터가 여러개 있는 것과 같다. 따라서 각각의 컨테이너는 자기만의 컴퓨터 공간(OS, 저장 공간, 프로그램 등)을 가지고 있다.
실행 중인 컨테이너 내부에 접속하기
docker exec -it 컨테이너명[또는 컨테이너 ID] bash
docker run -d nginx
docker exec -it [Nginx가 실행되고 있는 컨테이너 ID] bash
ls # 컨테이너 내부 파일 조회
cd /etc
ls
cd /nginx
ls
cat nginx.conf
- 컨테이너 내부에서 나오려면 Ctrl + D 또는 exit을 입력하면 된다.
- bash: 쉘(Shell)의 일종
- -it: -it 옵션을 사용해야 명령어를 입력하고 결과를 확인할 수 있다. -it 옵션을 적지 않으면 명령어를 1번만 실행시키고 종료되어 버린다. 즉, -it 옵션을 적어야 계속해서 명령어를 입력할 수 있다.
'CI,CD > Docker' 카테고리의 다른 글
[Docker] Dockerfile의 구조와 문법 + Spring Boot 프로젝트 Docker로 실행 (1) | 2024.07.21 |
---|---|
[Docker] 도커 볼륨(Docker Volume) (0) | 2024.07.19 |