Docker

허현진·2022년 4월 9일
0

Docker

목록 보기
1/1

가상서버 VS 컨테이너

  • 가상서버: 마치 한 대의 전용 서버가 있는 것처럼 이용
  • 컨테이너: 하나의 리눅스 프로세스가 마치 전용 서버에서 동작하고 있는 것 같은 분리 상태를 만들어 냄.(namespace, cgroup)

도커

  • 여러 마이크로서비스를 “한 대”의 물리적인 서버에서 운영할 수 있도록 만들어 줌.
  • 언어의 제한 X (PHP,JAVA,Python,NodeJs…)
    --> 이를 가능하게 해주는 커널 기술 : Cgroup, Namesapce
    --> 커널 기술 덕분에 일반적인 VM과 같은 물리적인 가상화를 쓰지 않아도 됨.

Cgroup

-Control group : 시스템의 CPU 시간, 시스템 메모리, 네트워크 대역폭과 같은 자원을 제한하고 격리할 수 있는 커널 기능

Namesapce

  • 시스템 리소스를 해당 프로세스에만 해당되는 자원처럼 보이도록 하고, 다른 프로세스와 격리시키는 가상화 기능
  • UTS, IPC, PID, MNT, NET, USER 기능

2.3 도커 이미지

  • 자바를 사용하여 개발하고 배포하려면
  1. 개발자 컴퓨터에서 개발하고 소스를 커밋한다.
  2. 빌드와 배포를 요청하면
  3. CI/CD 서버가 커밋 된 소스를 내려 받고 테스트와 빌드 한 다음 war, jar같은 배포 단위의 파일 뭉치(압축)를 만들고
  4. 원하는 환경의 서버에 이동시킨 후 실행한다.
  • 도커로 이러한 절차를 만들기 위해 파일 뭉치의 역할을 하는 것 : 도커 이미지
  • 도커를 실행하기 위해 필요한 컨테이너의 기초
  • 이미지 : 컨테이너 런타임 내에서 사용하기 위해 정렬된 루트 파일 시스템의 변경 사항 및 해당 실행 매개 변수의 모음. 컨테이너의 스냅샷으로 생각(상태X,변경X)
    -이미지는 변경이 불가능한 파일. 컨테이너의 파일은 수정 가능 --> 컨테이너 파일을 수정하고 나서 이미지를 만들면 된다.

스냅샷 형태로 이미지를 만드는 방법

  • docker pull nginx : 도커 이미지를 다운로드 하는 명령어
  • docker images : 로컬에 존재하는 모든 도커 이미지 보여주는 명령어
  • docker run –-name nginx -p 8000:80 -d nginx : 이미지를 컨테이너화 해서 도커를 실행시키기(RUN명령을 하면 이미지 파일이 존재하지 않으면 다운로드를 알아서 해줌)

--name옵션 : 컨테이너 이름 지정
-p: 도커 포트와 내 PC포트 연결, 내 피시 8000,도커80(내 PC 8000포트에 도커 컨테이너 80포트를 포트 포워딩)
-d : detached mode (백그라운드로 실행하겠다)
nginx : 도커 이미지의 이름

  • docker ps : nginx 도커 컨테이너가 잘 실행되고 있는지 확인
  • NGINX의 index.html 페이지 문구를 바꾸기
    -호스트 PC에서 도커로 연결하는 명령어는 attach
  • attach 명령어로 연결하면 nginx에 접속할 때 로그 확인 가능.
  • 터미널에 접속해서 index.html 파일의 위치를 찾아 우리가 만든 index.html 파일로 바꿔야 함.
  • 터미널 환경으로 접속하려면 호스트PC(외부) 에서 도커 컨테이너(내부)의 쉘을 실행해야 함
  • exec : 호스트에서 도커 컨테이너 안에 명령을 실행하는 명령어
  • docker exec -it nginx /bin/bash : 도커 컨테이너 내부 쉘이 실행되어 접근

ex) docker exec -it db bash : mysql 컨테이너의 내부 쉘에 실행되어 접근
- exec : 컨테이너 내부에 명령을 실행하도록 함
-i(interactive) 표준 입력을 활성화시키면 attach가 안 되어 있더라도 명령어 입력 가능.
-t(tty) 옵션을 사용하면 리눅스 쉘이 표시 됨.

리눅스 명령어(파일 찾기)

  • find / -name index.html 2>/deb/null

find : 파일 찾는 명령어
/ : 루트 디렉토리 -name : 파일 이름 지정 옵션 2>dev/null : 에러 출력을 저기로 버림.

  • docker cp nginx:/user/share/nginx/html/index.html index.html : 컨테이너 내의 index.html파일을 호스트 PC에 복사
  • docker cp index.html nginx:/usr/share/nginx/html/index.html : 수정한 index.html파일을 nginx 컨테이너에 복사해서 넣기

  • docker commit nginx mynginx : 컨테이너를 index.html 파일이 수정된 현재 상태의 이미지로 만들기.

  • 기존에 실행되고 있는 nginx 컨테이너를 종료하고 삭제한 다음 우리가 만든 이미지로 컨테이너 실행해야 함

docker rm [컨테이너 이름(NAMES)]: 삭제 명령어(실행되고 있는 컨테이너는 삭제되지 않음)

docker stop[컨테이너 이름]: 컨테이너 종료 명령어. docker ps로 확인하면 리스트에서 사라지고 웹브라우저에도 접속되지 않음. 하지만 컨테이너는 삭제되지 않았으며, 중지된 컨테이너는 원래 상태대로 실행이 가능함.

docker ps -a : 를 통해 중지된 컨테이너도 확인 가능

컨테이너 정지 후 삭제 가능!!

도커 시작 : docker run -d -p 80:80 docker/getting-started

도커 파일로 이미지를 만드는 방법 (= 이 방법은 배포할 파일 뭉치를 만드는 것과 같음)

도커 파일(Dockerfile)

  • 이미지를 명령어 묶음으로 만들 수 있는 텍스트 파일
  • 파일에 텍스트로 명령어를 기술하여 실행하면 이미지가 만들어짐
  • 현재 디렉토리에 Dockerfile.txt 파일 생성 후 txt 지우기

Dockerfile 내에 입력해야 할 소스

FROM nginx
COPY index.html /usr/share/nginx/html/

  • docker build -t mynginx2 . : 도커 파일을 이용하여 이미지를 만드는 명령어
    (위에서 작성한 Dockerfile 파일이 현재 작업 디렉토리에 있어야 함)
  • docker run –name custom1 -p 8002:80 -d mynginx2 : 컨테이너 실행
  • docker rmi [이미지 이름(REPOSITORY)] or docker rmi [이미지 아이디(IMAGE ID)]. : 도커 이미지 삭제 명령어

2.4 도커를 사용한 테스트 환경 구축

  • 마이크로 서비스 아키텍처로 운영하든 하지 않든 적어도 용도별로 서버가 두 대 정도 존재.
  • 도커가 나오기 전에는 서버 엔지니어가 자동화 스크립트 같은 것을 이용해서 해당 스크립트만 실행하면 애플리케이션 실행에 필요한 환경을 구축하였지만 도커를 도입하면 해당 번거러움이 없어짐.
    --> 도커 이미지를 만들어서 해당 실행 환경을 관리하면 되기 때문
  • 즉 도커를 이용하면 더 이상 물리적으로 늘어나는 서버에 대응할 필요가 없어짐. (컨테이너 숫자를 늘려주기만 하면 됨)
  • 도커를 사용하여 테스트 환경 구축 (도커를 적용하는 곳으로 테스트 환경이 가장 적절함)
  • 우리가 만든 VM인스턴스 리눅스에 접속하여 작업하려면 SSH를 통해 인스턴스에 연결해야 함.
    리눅스 쉘 접속
    https://docs/docker/com/install/linux/docker-ce/debian/ 사이트 접속
    • sudo usermod -aG docker $USER : 일반 계정 유저도 도커 사용 가능

$USER : 현재 사용자에게 원한을 준다 ( 특정 사용자에게 권한을 부여하려면 $USER대신 사용자 아이디 넣기)

MySQL 컨테이너 구동

  • https://hub.docker.com/_/mysql : 도커 허브 사이트를 방문
  • Starting a MySQL instance is simple 부분 실행

    docker run --name db -e MYSQL_ROOT_PASSWORD=1234 -p 3306:3306 -d mysql:5.7.28

_5.7.28 : 태그 부분
TAG : 해당 이미지의 버저닝을 할 때 쓰는 것으로 이미지의 버전에 따라 태깅을 함.

ex. MySQL8버전을 사용하고 싶다면 명령어 부분을 MySQL:8.0으로 수정
태킹해서 도커 이미지를 분리할 경우, 사용하고 싶은 버전의 tag만 알면 이미지를 손쉽게 사용 가능. 도커 이미지로 배포할 경우 유용하게 사용됨

SpingBoot를 컨테이너화

  • 개발자가 로컬 환경에서 개발하고 나서 Git에 푸시 하면 해당 소스를 테스트 서버로 배포해야 함.
    (배포는 Jenkins로 하지만 수작업으로 한다 가정)

  • 배포 서버에서 해당 프로젝트가 빌드 되었다고 가정하면 SpringBoot의 jar파일이 만들어짐. 그럼 이 jar파일을 포함하여 컨테이너를 실행해야 함

  • jar 파일 클론 후 해당 위치에서 Dockerfile생성 ( vi Dockerfile)

docker/target/docker-0.0.1-SNAPSHOT.jar이 있는 것 확인

Dockerfile 내용

  1. FROM openjdk:8-jdk-alpine
  2. ADD docker/target/docker-0.0.1-SNAPSHOT.jar app.jar
  3. ENTRYPOINT [“java”,”-Djava.security.egd=file:/dev/./urandom”,”-Dspring.profiles.
  4. active=dev”,”-jar”,”/app.jar”]

Jar 파일을 적절하게 수정해서 실습

- FROM <이미지> : base이미지 지정 (Dockerfile내의 최상단에 위치, Docker Hub와 같은 Docker repository에 올려놓은 잘 알려진 공개 이미지인 경우가 많음)

- ADD (COPY) : 호스트 컴퓨터에 있는 디렉터리나 파일을 Docker 이미지의 파일 시스템으로 복사하기 위해 사용됨. (ADD는 COPY의 강력한 버전)
!! 이거 agr1에 현재 경로 기준으로 .jar파일 입력해 주어야 함!! 

- ENTRYPOINT : 이미지를 컨테이너로 띄울 때 항상 실행되야 하는 커맨드를 지정할 때 사용. Docker 이미지를 마치 하나의 실행 파일처럼 사용할 때 유용함 (컨테이너가 뜰 때 ENTRYPOINT 명령문으로 지정된 커맨드가 실행되고, 이 커맨드로 실행된 프로세스가 죽을 때, 컨테이너도 따라서 종료되기 때문)
  • 도커 이미지는 각각의 이미지들을 서로 layer시키는 구조로 되어 있음. 베이스가 되는 이미지를 layer아래에 read only로 마운트 시키고, 컨테이너에서 프로세스로 쓰는 파일 시스템 부분을 read write로 마운트 시킴.

SpringBoot이미지에서 read only 부분이 openjdk:8-jdk-alpine. read write 부분이 jar 파일로 배치될 부분

  • Docker inspect : 참조한 이미지 확인
  • Docker build -t springboot . : 도커 빌드로 이미지 생성
  • Docker run –-name app1 -d –p 80:8080 springboot : 생성된 도커 이미지를 바탕으로 도커 컨테이너 명령어 실행
    --> 34.134.162.253 (외부 IP주소) 입력하면 웹 브라우저 뜸
  • Docker logs app1 : 실행된 컨테이너에 대해 로그 볼 수 있음
  • Docker logs [option] 컨테이너명

[option]
-f : 실행되는 로그를 계속해서 볼 수 있음
--tail 100 : 마지막 100라인을 볼 수 있음
(도커 모니터링 툴을 운영하고 있다면 직접 접속해서 명령을 실행하지 않아도 됨)

도커의 장점 : 하나의 인스턴스에 MySQL, Springboot 등과 같이 인스턴스 사양에 따라 여러 프로그램의 컨테이너를 손쉽게 설치할 수 있음.

배포 과정

Developer ---(빌드 요청)--> CI 서버 --> 테스트 서버

  • 대부분은 배포 서버가 따로 있음. 배포 서버는 별도의 서버를 사용하여 서비스가 운영되는 서버로 해당 어플리케이션 뭉치를 배포하는 역할만 담당

대표적인 CI 프로그램은 젠킨스

  • 예전 : CI 서버에서 해당 애플리케이션에 대해 새 소스를 빌드하고, 빌드된 파일 뭉치(jar,war) 파일을 운영하는 서버로 전송하여 애플케이션을 재시작 하면 작업 끝났음.
  • 하지만 도커는 컨테이너가 새로 빌드 된 파일 뭉치를 포함하여 실행하여야 함.
  • 예전 : CI 서버에서 서비스를 운영하는 서버로 빌드 된 파일 뭉치만 전송하고, 실행되고 있는 컨테이너에 파일 뭉치를 복사한 후 컨테이너를 재시작 하였음.
  • 이름이 app1인 컨테이너에 새로 빌드 된 파일 뭉치를 배포한 후 다시 실행하면 됨.

    Docker cp app1:app.jar . : 파일 뭉치를 실행 중인 컨테이너에 복사하는 명령 실행.
    docker restart app1 : 다시 실행

파일 뭉치 : app.jar / 실행 중인 컨테이너 : app1

  • 도커 호스트 환경에 있던 파일을 컨테이너로 복사 가능(컨테이너의 파일도 호스트 서버의 파일이기 때문에 물리적으로 복사 가능)
  • 호스트 서버의 파일을 컨테이너로 복사
    docker cp 호스트파일 컨테이너명:복사되는 위치/파일명
  • 컨테이너의 파일을 호스트 서버로 복사
    docker cp 컨테이너명:파일위치/파일명 호스트 서버 디렉토리 위치

CI와 도커 레지스트리를 이용한 테스트 배포

도커 레지스트리

  • 도커 이미지 생성 : 실제로 빌드 시 CI/CD 서버에서 도커 이미지를 생성하여 개발 환경으로 배포해야 함.
  • 도커 레지스트리 : 도커 이미지를 서비스를 운영하는 서버에 배포하는 방법 제공
    https://hub.docker.com
  • 도커 레지스트리는 로컬이나 특정 서버에 설치해서 운영 가능하지만 도커 허브나 클라우드, CI/CD에서 제공하는 걸 사용하는 것이 효율적
  • 레지스트리는 소스 저장소와 비슷. Git을 사용하는 Github, Bitbucket 등이 소스를 저장할 때 비슷한 방식을 사용하듯 레지스트리도 제공하는 벤더가 다를 뿐 저장 방식은 비슷
  • 도커 허브 : 대표적인 도커 레지스트리
  1. docker login : 도커 허브 사이트의 계정 정보를 이용하여 로그인
    --> 로그인 상태가 되면 도커 허브 사이트에서 부여한 도커 레지스트리에 도커 이미지 저장 가능
  2. docker tag springboot heohyeonjin/custom-nginx:springboot
    docker tag 이미지명 도커허브아이디/이미지명:태그
  3. docker push heohyeonjin/custom-nginx:태그명
    : push 명령어를 이용하여 이미지를 도커 허브로 푸시
  • 이전 테스트 서버 환경을 구출할 땐 그냥 도커 파일을 만들고 테스트 환경 자체에서 이미지를 만들어 배포하는 방식이었다면, 이제는 이 수작업의 역할을 CI 서버가 대신함. CI서버를 사용하면 도커 이미지의 물리적인 위치 또한 달라지기 때문에 앞에서 다른 도커 레지스트리 또한 사용할 것임.
  • 서버의 구성에 CI와 도커 레지스트리가 추가됨.
  • CI 서버에서 빌드를 하고 도커 이미지 생성

물리적으로 다른 위치에 있는 테스트 서버에 배포 방법

  1. 도커 레지스트리 사용 (도커 허브 사용)
  • 도커에서의 리포지토리 개념도 Github와 마찬가지. 즉 프로젝트 하나의 저장소.
  • 만약에 서비스가 두 개의 애플리케이션으로 구성된다면 리포지토리도 두 개 있어야 함.
  1. 직접 도커 레지스트리 운영
  • 레지스트리를 직접 운영하는 경우 : 도커 허브나 다른 퍼블릭 레지스트리에는 회사 보안 정책 때문에 접근할 수 없는 경우

도커 레지스트리를 직접 만들고 사용하는 방법

  1. 도커 레지스트리 이미지 다운로드 : docker pull registry
  2. 도커 레지스트리 컨테이너 생성 : docker run -d –p 5000:5000 --restart=aways --name registry registry
  3. 도커 이미지 저장 : docker pull ubuntu
  4. 도커 이미지 태깅 : docker image tag ubuntu localhost:5000/ubuntu(커밋 느낌?)
    이미지 리스트에서 태깅한 localhost:5000/ubuntu 확인 가능
  5. 생성했던 컨테이너인 localhost:5000으로 이미지 푸시 : docker push localhost:5000/ubuntu

레지스트리도 도커 이미지를 바탕으로 컨테이너를 실행하여 만드는 것임.

도커 레지스트리 설치가 잘 되었는지 테스트하는 방법
: 로컬에서 도커 이미지 받아보기.
1. 구글 클라우드의 방화벽 규칙에서 5000번 허용
2. 로컬에서 클라우드에 있는 도커 레지스트리 다운로드
: docker pull 34.134.162.253:5000/ubuntu
클라우드 인스턴스에 설치된 레지스트리에서 이미지를 다운로드 받으려고 하니 에러가 남. 기본적으로 도커 레지스트리는 HTTPS로 통신가능해야 함.
(https://docs.docker.com/registry/insecure/에 자세히 설명)

3. Docker Engine에서 insecure-registries :[“34.134.162.253:5000”] 작성
4. 도커 서비스 재시작 : sudo systemctl restart docker

  • 도커 허브와 프라이빗 레지스트리를 사용하여 도커 이미지를 저장할 수 있는 레지스트리의 구성 완료

  • 이후 레지스트리를 사용하여 CI 서버에서 새로운 소스의 도커 이미지를 빌드 한 다음, 레지스트리에 푸시 하고 테스트 서버에서는 푸시 된 최신의 이미지를 다운로드 받아서 다시 컨테이너로 실행하면 도커 레지스트리를 이용한 배포 프로세스가 완성됨.

도커 레지스트리를 이용한 배포의 장점

  1. 롤백 시 사용
  • 도커 레지스트리를 이용하는 이유가 단지 CI 서버와 테스트 서버의 물리적인 공간이 다르기 떄문만은 아님.
  • 반영한 소스에 에러가 나서 롤백 용이
  • 도커에서는 태깅을 롤백의 의미로도 사용 가능함. 릴리즈 버전별로 태깅을 해놓고 어떤 에러가 나서 롤백이 필요한 상황이 되면, 가장 안정적인 버전으로 태깅된 이미지를 베이스로 컨테이너를 실행하면 됨.
  1. 로컬에 테스트 시

2.5 네트워크

네트워크의 종류

  • 브릿지 모드
  • Host 모드
  • Container 모드
  • None 모드

2.6 Infra as code

  • 컨테이너 생성의 기본이 되는 이미지를 생성하는 부분은 도커 파일을 써서 컨테이너의 내부가 어떻게 구성되는지 코드만 보고 알 수 있고, 변경되는 사항이 생기면 코드를 수정해서 변경할 수 있는 인프라 코드 환경이 만들어져 있음.

    FROM ADD ENTERPOINT ..

docker-compose

: 컨테이너를 실행하는 구문을 docker-compose.yml 이라는 파일에 모아 놓고 실행 구문을 직접 커맨드 라인에 실행시킬 필요 없이 docker-compose 실행 구문을 통해 실행할 수 있도록 하는 것.
(인프라를 코드화 할 수 있게 도와주는 도구)
--> 컨테이너를 실행하는 명령을 직접 실행하지 않고 docker-compose.yml이라는 파일에 저장하고 해당 파일을 실행하기 때문에 확장자가 yml이라는 코드 파일에 저장할 수 있음

Ansible(앤서블)
: docker를 적용할 때 docker-compose 이외에 사용했던 쉘스크립트를 코드화 해주는 툴

2.7 도커의 한계

  • 특정 성능의 호스트 인스턴스를 사용하고 있을 때, 서비스 사용자가 갑작스럽게 증가하여 호스트 서버의 규모를 확대해햐 하는 순간이 오면,
  • 호스트 서버의 성능을 스케일업 하고 도커를 설치해서 운영하던 컨테이너를 다시 실행해야 함.
  • 그런데 해당 시점의 폭발적인 트래픽 증가는 일시적인 현상으로 그치고, 다시 사용자 트래픽이 제자리에 돌아왔다면 인프라 비용의 절감을 위하여 호스트 서버의 성능을 다운그레이드 해서 컨테이너를 다시 실행해야 함.
  • 오케스트레이션을 사용하면 도커의 단점인 단일 호스트에서 발생할 수 있는 문제점을 해결해 줌.
  • 오케스트레이션을 활용하면 여러 개의 호스트를 단일 호스트처럼 사용할 수 있음.

오케스트레이션 사용 시

  • 컨테이너 프로비저닝 및 배포
  • 컨테이너 중복성 및 가용성
  • 컨테이너 인프라 확장 또는 제거로 호스트 인프라 전체에 애플리케이션 로드를 균등하게 분산
  • 호스트에 리소스가 부족하거나 호스트가 죽은 경우 한 호스트에서 다른 호스트로 컨테이너 이동
  • 컨테이너 간 리소스 할당
  • 내부 컨테이너에서 실행되는 서비스의 외부 노출
  • 컨테이너 간 서비스 검색 로드 밸런싱
  • 컨테이너 및 호스트의 상태 모니터링
  • 애플케션을 실행하는 컨테이너와 관련하여 애플리케이션 구성
profile
코딩일지..

0개의 댓글