Victoree's Blog

[1] 도커 이미지와 컨테이너 본문

Infra/Docker

[1] 도커 이미지와 컨테이너

victoree 2021. 4. 26. 21:38
728x90

1. 도커 이미지와 컨테이너

1) 도커 이미지

  • 컨테이너를 생성할 때 필요한 요소
  • 여러 개의 계층으로 된 바이너리 파일로 존재
  • 컨테이너를 생성하고 실행할 때, 읽기 전용으로 사용
  • [저장소 이름]/[이미지 이름]:태그로 구성

2) 도커 컨테이너

  • 도커 이미지를 기반으로 컨테이너를 생성할 수 있음
  • 해당 이미지의 목적이 맞는 파일이 들어있는 파일 시스템과 격리된 시스템 자원 및 네트워크를 사용할 수 있는 독립적 공간이 생성
  • 이미지에서 변경된 사항만 컨테이너 계층에 저장
  • 컨테이너에서 하는 작업은 원래 이미지의 영향을 받지 않음
  • 생성된 컨테이너는 독립된 파일 시스템을 제공받으며 호스트와 분리되어 있음
  • 특정 컨테이너에서 어플리케이션을 설치하거나 삭제해도 다른 컨테이너와 호스트는 변화없음

2. 도커 컨테이너 다루기

도커 컨테이너 생성

  • docker : docker 클라이언트 언급
  • run : 컨테이너 생성 및 실행
  • <이미지> : 해당 컨테이너를 위한 이미지

-it란?

  • -it를 붙여줘야 명령어를 실행한 후 계속 명령어를 적을 수 있음
  • -i
    • interactive 상호 입출력
  • -t
    • terminal
    • tty(유닉스 계열 운영체제 명령어)를 활성화해서 배시 셸을 사용하도록 설정
  • -it가 없다면, 그냥 redis-cli를 키고 밖으로 다시 나와버림
  • exit 또는 command+C로 종료할 수 있으나, 이는 도커 컨테이너를 종료시키고 빠져나옴
    • Command + P,Q 를 입력하면 컨테이너의 쉘에서만 빠져나옴

 

3. 이미지 내부 파일 시스템 구조 보기

$ docker run <이미지> __명령어___

  • 명령어 : 이미지가 가지고 있는 시작 명령어를 무시하고 여기에 있는 커맨드를 실행하게 함
  • 특정 이미지 안에 ex) ls라는 명령어를 실행가능하게 하는, 해당 이미지의 파일 스냅샷 안에 ls를 실행할 수 있게 하는 파일이 있어야 실행가능함

 

4. 컨테이너 나열하기

  • $ docker ps : process status
    • CONTAINER ID : 컨테이너 고유한 아이디 해쉬값 (일부분)
    • IMAGE : 컨테이너 생성시 사용한 도커이미지
    • COMMAND : 컨테이너 시작시 실행될 명령어, 대부분 이미지에 내장되어 있으므로 별도의 설정이 필요없음
    • CREATED : 컨테이너가 생성된 시간
    • STATUS : 컨테이너의 상태
      • 실행중은 Up, 종료는 Exited, 일시정지 Pause
    • PORTS : 컨테이너가 개방한 포트와 호스트에 연결한 포트
    • NAMES : 컨테이너 고유한 이름
      • 컨테이너 생성시 --name 옵션으로 이름을 설정하지 않으면 도커 엔진이 임의로 형용사와 명사를 조합해 설정함
      • id와 마찬가지로 중복이 안되고, docker rename 명령어로 변경할 수 있음
  • $ docker run <이미지> ping localhost 으로 컨테이너가 살아있는지 확인할 수 있음
  • -a 옵션으로 정지된 컨테이너를 포함한 모든 컨테이너의 목록을 볼 수 있음

 

5. Docker Lifecycle

  1. 생성(create) -> 시작(start) -> 실행(running)
  • $ docker run <이미지 이름>
    • $ docker create <이미지 이름> + $ docker start <시작할 컨테이너 아이디/이름>
    • $ docker create <이미지 이름>
      • 이미지에 있는 파일 스냅샷을 컨테이너의 하드디스크에 올려줌
      • 해당 작업을 한 컨테이너의 id값을 리턴함
    • $ docker start -a <시작할 컨테이너 아이디/이름>
      • '-a' : attach
        • 도커 컨테이너가 실행될 때, 해당 컨테이너에서 나오는 output을 모두 화면에 표출해줌
      • 컨테이너에 프로세스를 시작해줌
      • 포그라운드 식으로 이미지를 동작시켰기 때문에, 백그라운드로 실행할 수 없음
  1. 중지
  • 아래 명령어 둘 다 컨테이너를 중지시킴
  • $ docker stop <중지할 컨테이너 아이디/이름>
    • gracefully 하게 중지시킴
    • 자비롭게 그동안 하던 작업들을 완료후 컨테이너들을 중지시킴
    • SIGTERM을 날려 grace period(정리하는 시간)을 두고, SIGKILL을 날려 정지시킴
  • $ docker kill <중지할 컨테이너 아이디/이름>
    • 바로 컨테이너를 중지시킴
    • 바로 SIGKILL을 날림
  • $ docker stop $(docker ps -a -q)
    • 모든 컨테이너의 아이디를 중지하는 명령어
  1. 삭제
  • $ docker rm <삭제할 컨테이너 아이디/이름>
    • 실행중인 컨테이너는 중지한 후 가능함
  • 모든 컨테이너를 삭제 : $ docker rmdocker ps -a -q``
  • 이미지 삭제 : $ docker rmi <이미지 id>
  • 한번에 컨테이너, 이미지, 네트워크 모두 삭제 : $ docker system prune
    • 도커를 쓰지 않을때, 모두 정리하고 싶을 때 사용하면 좋음
    • 이것은 실행중인 컨테이너에는 영향을 주지 않음
    • $ docker volume prune과 같이 원하는 오브젝트를 전부 지우는 것도 가능함
  • $ docker rmi $(docker images -f "dangling=true" -q)
    • 이름없는 이미지 none || : 이미지 제거
  • $ docker rm $(docker ps -a -q)
    • 모든 컨테이너의 아이디를 삭제하는 명령어

 

> 실행중인 컨테이너에 명령어 전달

  • $ docker exec <컨테이너 아이디>
  • docker run 명령어 v.s. docker exec
    • run : 새로 컨테이너를 만들어 해당 명령어를 실행시킴
    • exec : 이미 실행중인 컨테이너에 명령어를 실행시킴

> 실행중인 컨테이너에서 터미널 생활 즐기기

  • $ docker exec -it <컨테이너 아이디> <sh/zsh/bash>
  • 컨테이너를 쉘 환경으로 접근하기가 가능함

> 레디스를 이용한 컨테이너 이해

  • 레디스 서버가 먼저 작동하고 있어야 함 -> 레디스 클라이언트(redis-cli) 실행 후 명령어를 레디스 서버에 전달
    1. docker run redis
    2. redis-cli
  • 레디스 클라이언트가 레디스 서버가 있는 컨테이너 밖에서 실행을 하려 하니 레디스 서버에 접근을 할 수 없어 에러가 발생
  • 레디스 클라이언트도 컨테이너 안에서 실행을 시켜야 함
    1. docker run redis
    2. docker ps
    3. docker exec -it <컨테이너 아이디> redis-cli

 

6. 컨테이너를 외부에 노출

1) 컨테이너 실행 명령어 바꾸기

  • docker run 이미지 이름
  • $ docker run -p 49160:8080 이미지 이름
    • 로컬 파일(package.json, index.js)을 컨테이너에 복사해줌
    • 네트워크도 마찬가지로 로컬 네트워크에 있던 것을 컨테이너 내부에 있는 네트워크에 연결시켜주어야함

  • ![Image]({{ site.baseurl }}/images/docker_network.png)
    • 컨테이너 내부의 8080이라는 포트에 바로 접근하려면 매핑을 해주어야 함
    • 49160은 로컬 브라우저의 포트로 가면, 컨테이너의 8080으로 매핑됨
  • 호스트의 특정 IP를 사용하려면 192.168.0.100:8000:8080 과 같이 바인딩할 IP와 포트를 명시
    • 또한 여러개의 포트를 외부에 개방하려면 -p 옵션을 여러번 써서 설정할 수 있음
    • $ docker run -it -p 5000:8080 -p 192.168.0.100:8000:8080 ubuntu:14.04

2) 컨테이너 어플리케이션 구축

  1. mysql 이미지를 이용해 데이터베이스 컨테이너 생성
  2. docker run -d \ > --name wordpressdb \ > -e MYSQL_ROOT_PASSWORD=password \ > -e MYSQL_DATABASE=wordpress \ > mysql:5.7
  3. 워드프레스 이미지를 이용해 워드프레스 웹 서버 컨테이너 생성
  4. docker run -d -e WORDPRESS_DB_PASSWORD=password --name=wordpress --link wordpressdb:mysql -p 80 wordpress
  5. $ docker ps로 연결된 포트 확인 후 접속해보기
  • d : detach 의 줄임말
    • 컨테이너 실행 후 바로 터미널에서 빠져나오기
    • 백그라운드 전용으로 이미지를 실행시켰기 때문에 -a(포그라운드)로 접근이 불가능함
    • 대신 exec 옵션을 통해 해당 컨테이너에 접속할 수 있음
  • e
    • 컨테이너 내부의 환경변수 설정
  • link
    • 컨테이너 A가 B 컨테이너로 접근하는 간단한 방법은 NAT으로 부터 할당받은 내부 IP를 사용하는 것
    • 도커 엔진은 내부 IP를 순차적으로 할당하기 때문에 alias로 접근하도록 설정 가능
    • 단, wordpressdb가 종료된 상태에서 wordpress 컨테이너를 실행하면, 오류가 출력됨
    • 컨테이너의 연결뿐만 아니라 컨테이너 실행 순서의 의존성도 정의해줌

7. 도커 볼륨

  • 이미지는 읽기전용으로 사용하고, 컨테이너의 변경사항은 컨테이너 레이어에 저장됨
  • 컨테이너를 삭제하면, 컨테이너 계층에 저장되어 있던 데이터가 같이 삭제됨
  • 데이터를 영속적인 데이터로 활용하기 위해 볼륨을 이용함
  1. 호스트 볼륨 공유
    • --v /home/data:/var/lib/mysql
    • 호스트에 특정 주소와 컨테이너 내부 주소를 매핑시켜서 볼륨을 공유하는 방식
    • 동기화가 아니라 완전히 같은 디렉토리
    • 이미 해당 디렉토리에 특정 파일이 있다면, 덮어씌워짐
  2. 볼륨 컨테이너
    • 1번의 방식으로 호스트와 볼륨을 공유한 컨테이너로 부터 볼륨을 공유받는 방식
    • --volumes-from 먼저_공유한_컨테이너명
    • 1번에 공유한 /home/data라는 디렉토리를 공유받음
  3. 도커 볼륨
    • $ docker volume create --name myvolume라는 명령어로 볼륨을 생성
    • $ docker volume ls를 통해 볼륨 확인 가능
    • 로컬 호스트에 저장되며 도커 엔진에 의해 생성됨
    • --v [볼륨의 이름]:{컨테이너의 공유 디렉토리}으로 설정 가능함
    • 해당 볼륨이 실제로 호스트의 어느 주소에 있는지는 알 필요 없음
      • 하지만 확인이 하고 싶다면 $ docker inspect라는 명령어를 통해 확인할 수 있음
      • MountPoint라는 데이터를 통해 확인할 수 있음
    • 그냥 -v /root라고 옵션을 주게되면, auto_volume이 생성됨
    • docker volume prune으로 싹 다 지울 수 있음
728x90

'Infra > Docker' 카테고리의 다른 글

[5] Dockerfile  (0) 2021.05.28
[4] Docker 이미지  (0) 2021.04.26
[3] Docker Logging 및 자원 할당  (0) 2021.04.26
[2] Docker Network  (0) 2021.04.26
[0] Docker에 대해 알아봅시다!  (0) 2021.04.26
Comments