728x90

마이크로서비스 및 DevOps


모놀로식 아키텍처

특징

  • 단일 프로세스에서 실행되거나 몇몇 시스템에서 몇 개의 프로세스로 실행되는 거대한 모놀리식 애플리케이션

 

장점

  • 간단한 개발
  • 간편한 배포
  • 단순한 확장성

 

단점

  • 코드 품질이 낮아짐
  • 애플리케이션의 시작이 오래 걸림
  • 애플리케이션의 확장이 어려움
  • 컴포넌트별 개발의 어려움
  • 다양한 기술 적용의 어려움

 


 

마이크로서비스 아키텍처

특징

  • 모놀로식 아키텍처의 크기가 커짐에 따라 발생하는 문제점을 극복하기 위해 마이크로서비스라는 기능적으로 세분화되고 독립적으로 작동하는 방식 사용

 

장점

  • 크고 복잡한 애플리케이션을 지속적으로 배포할 수 있음
  • 향상된 유지 보수성 각 서비스는 작기 때문에 이해하고 변경하기 쉬움
  • 테스트 용이성 각 서비스는 독립적으로 테스트 가능
  • 배포 효율성 각 서비스는 독립적으로 배포 가능
  • 독립적으로 개발 테스트 배포 및 확장
  • 개발에 생산성이 높고 배포 속도가 높음
  • 다양한 기술 적용 가능

 

단점

  • 분산 시스템 설계에 따른 복잡성
  • 서비스 간 통신 매커니즘을 따로 구현
  • 서비스 간 상호 작용 테스트
  • 배포 및 관리 운영상의 복잡성
  • 증가된 리소스 소비

 


 

DevOps

작동 방식

  • DevOps 모델에서는 개발팀과 운영팀의 서로 단절되었던 역할들이 서로 조율하고 협업하여 더욱 안정적이고 뛰어난 제품을 생산할 수 있도록 지원

 

장점

  • 출시 시간 단축
  • 시장과 경쟁 지형에 따른 유연한 대응
  • 시스템 안정성 및 신뢰성 유지
  • 평균 복구 시간 개선

 


 

쿠버네티스란


쿠버네티스

  • 여러 컨테이너 오케이스트레이션 도구 중 현재 가장 주목받고 있는 도구
  • 구글에 의해 개발된 컨테이너 오케스트레이션 도구
  • 기본적으로 도커 플랫폼 사용

 

도커

  • 도커 엔진이 설치된 단일 시스템에서 다수의 컨테이너를 구동하는 방식으로 쉽게 구성 가능
  • 단일 시스템만으로는 확보할 수 있는 자원이 한정되어 있어, 구동 가능한 서비스의 한계가 있음
  • 도커 엔진이 구동되고 있는 시스템에 장애가 발생할 경우, 해당 시스템의 컨테이너를 사용하는 모든 서비스가 중지될 수 있는 가능성이 있음

 

오케이스트레이션

  • 다수의 시스템과 애플리케이션을 쉽게 설정하고 유지 관리할 수 있는 방식 의미
  • 도커 자체적으로 '도커 스웜'을 통해서 오케스트레이션을 지원하고 있음
  • 도커 스웜은 도커와 유사한 동작 방식으로 쉬운 사용법을 제공하고 있으나 기능이 비교적 단순하고 세세한 조정이 어려운 단점이 있음

 

쿠버네티스 아키텍처

  • 쿠버네티스 클러스터는 여러 시스템의 연결로 구성
  • 마스터와 노드 구성 요소로 분류할 수 있음
  • 필요에 따라 추가 요소(애드온)가 있을 수 있음
  • 쿠버네티스 클러스터 구성 요소

[출처] https://kubernetes.io/ko/docs/concepts/overview/components/

 


 

쿠버네티스 구성 요소

 


 

마스터 노드

  • 쿠버네티스 클러스터를 구성하기 위한 핵심 요소들의 모음
  • 클러스터를 조정하기 위한 컨트롤 플레인을 제공함
  • 노드에 작업을 분재하는 스케쥴링 등 클러스터에서 전반적인 결정을 수행하고 대응이 필요한 클러스터 이벤트를 감지하고 이에 대응하는 역할 수행
  • 마스터의 기능: API 서버, etcd, 스케줄러, 쿠버네티스 컨트롤러 관리자, 클라우드 컨트롤러 관리자

 

kubectl

  • 쿠버네티스 클러스터에 명령을 내리는 역할
  • 바로 실행되는 바이너리 형태로 배포됨
  • 주로 API 서버와 통신함

 

API 서버

  • 쿠버네티스 클러스터의 중심 역할을 하는 통로
  • 주로 etcd와 통신
  • API는 서로 다르게 구성되어 있는 기능들이 데이터를 주고 받기 위한 방식으로 인터페이스를 뜻함
  • 쿠버네티스의 구성 요소들은 마스터의 API 서버와 메세지를 주고 받게 되고 API 서버가 허브 역할을 수행하여 모든 요청을 수신하며 명령을 전달하는 역할 수행

 

etcd

  • etc 디렉토리 + distributed(퍼뜨렸다) 합성어
  • 쿠버네티스 클러스터의 모든 정보 데이터를 저장하는 저장소
  • 데이터 저장 시 'key-value' 형태로 데이터를 저장함
  • 데이터 백업에 대하여 반드시 고려할 필요가 있음

 

scheduler

  • 클러스터 내에서 생성되는 파드를 감지하고 실행할 노드를 선택하는 역할을 수행하는 구성 요소
  • 리소스 상태, 하드웨어/소프트웨어/정책 상의 제약, 어피니티 등 다양한 기존에 따라 배치 결정

 

쿠버네티스 컨트롤러 매니저

  • API 서버를 통해 클러스터의 상태를 감시하고, 필요한 상태를 유지하는 기능을 수행하는 구성 요소
  • 컨트롤러 종류
종류 설명
노드 컨트롤러 노드를 관리하며 노드가 다운되었을 때 알림 및 대응
레플리케이션 컨트롤러 복제 컨트롤러를 사용하는 모든 오브젝트를 관리하며 알맞은 수의 파드를 유지하는 기능
엔드포인트 컨트롤러 서비스와 파드 연결
서비스 어카운트 및 토큰 컨트롤러 쿠버네티스의 네임스페이스, 계정, 토큰 담당

 

클라우드 컨트롤러 관리자

  • AWS, GCP 등 각 클라우드 서비스와 클라우드에서 동작하는 쿠버네티스 구성 요소가 상호 작용할 수 있도록 해주는 기능
  • 쿠버네티스 1.6에서 도입된 알파 기능
  • 클라우드 환경에서 쿠버네티스 컨트롤러가 하는 역할 수행

 


 

워커 노드

  • 쿠버네티스의 컨테이너가 동작하는 런타임 환경을 제공하며, 동작 중인 파드를 유지하는 기능 담당
  • 노드의 역할: 큐블릿, 프록시, 컨테이너 런타임

 

kubelet

  • 쿠버네티스 클러스터의 각 노드에서 실행되는 에이전트로 마스터로부터 제공받는 파드의 구성 정보, 즉 노드가 수행하여야 할 작업을 전달받아서 컨테이너가 확실하게 동작하도록 보장하는 역할 수행

 

프록시

  • 클러스터의 각 노드에서 실행되는 네트워크 프록시로 '서비스'를 구현하기 위한 기능 담당
  • 클러스터 내부 간 통신이나, 클러스터 외부에서 내부로 전달되는 통신 등 호스트 레벨의 네트워크 규칙을 구성하고 외부 연결을 파드에 포워딩하며 서비스의 추상화 제공

 

컨테이너 런타임

  • 각 노드에서 실제 컨테이너의 동작을 책임지는 구성 요소
  • 파드 안에서 다양한 종류의 컨테이너가 문제 없이 작동하게 만드는 표준 인터페이스
  • 구성 요소: docker, containerd, CRI-O, rktlet, Kubernetes CRI

 

파드

  • 한 개 이상의 컨테이너로 단일 목적의 일을 하기 위해서 모인 단위
  • 파드는 언제라도 죽을 수 있는 존재임

 

네트워크 플러그인

  • 쿠버네티스 클러스터의 통신을 위해서 네트워크 플러그인을 선택하고 구성해야 함
  • 네트워크 플러그인은 일반적으로 CNI로 구성함
  • CNI: 컨테이너 네트워크 인터페이스로 컨테이너의 네트워크 안정성과 확장성을 보장하기 위해 개발됨
  • CNI 종류: 캘리코, 플래널, 실리움, 큐브 라우터, 로마나, 위브넷 등

 

CoreDNS

  • 빠르고 유연한 DNS 서버
  • 쿠버네티스 클러스터에서 도메인 이름을 이용하여 통신하는 데 사용
  • 도메인 네임을 편리하게 관리해주는 CoreDNS를 일반적으로 사용함

 


 

쿠버네티스 추가 요소

항목 설명
클러스터 DNS 쿠버네티스 클러스터 내의 여러 오브젝트(파드, 컨테이너, 서비스 등)에 대하여 주소 기반으로 오브젝트를 접근할 수 있는 DNS 서비스 제공
대시보드 쿠버네티스 클러스터 구성 및 모니터링을 위한 웹 기반 인터페이스 제공
컨테이너 리소스 모니터링 컨테이너 리소스 사용량의 시계열 매트릭스 기록
클러스터 로깅 컨테이너 로그를 중앙 로그 저장소에 저장하고 관리

 

쿠버네티스 API

  • API 버전 규칙
쿠버네티스의 모든 구성 요소는 API 오브젝트로 취급되며, API 서버를 통해 API로 메세지를 주고 받음
쿠버네티스는 리소스를 쉽게 표현하기 위해, 'api/v1' 또는 '/apis/extensions/v1beta1'과 같이 각각 다른 API를 호출하여 사용할 수 있음
같은 종류의 리소스라고 하더라도 서로 다른 API 버전이 존재할 수 있으며, API 버전이 다르다는 것은 안정성이나 기술 지원의 수준이 다르다는 것을 의미함
  • API 버전 종류: 알파 버전 API, 베타 버전 API, 안전화 버전 API

 

메니페스트

  • 쿠버네티스는 클러스터의 상태를 나타내기 위해 오브젝트 객체를 정의하여 사용함
  • 오브젝트를 생성할 때는 오브젝트의 기본 정보, 오브젝트의 상세 스펙을 정확하게 제시해야 함
  • YAML, JSON 문법으로 정의할 수 있음
  • 오브젝트 정의 시 필수 요구 필드 값
필드 값 설명
apiVersion 오브젝트를 생성하기 위한 API 버전 지정
kind 오브젝트의 종류 명시
metadata name, label, namespace 등 기본적인 정보 기술
spec 오브젝트의 세부 상태 정의

 

오브젝트 관리

  • 명령형 명령어: kubectl 명령 실행 시 오브젝트 생성에 필요한 정보 인수 또는 옵션을 사용하여 전달하는 방식
  • 명령형 오브젝트 구성: 오브젝트에 대한 세부 사항을 YAML/JSON 포맷으로 작성하고, kubectl 명령은 작성된 파일을 참고하여 실행하는 방식
  • 선언형 오브젝트 구성: 특정 디렉토리에 오브젝트 파일을 배치하는 방식, kubectl 명령은 특정 디렉토리에 배치된 오브젝트 파일을 참고하여 오브젝트 관리

 


 

쿠버네티스 클러스터 구성 도구

kubespray

  • 상용 서비스에 적합한 보안성과 고가용성이 있는 쿠버네티스 클러스터를 배포하는 오픈 소스 프로젝트
  • 서버 환경 설정 자동화 도구인 앤서블 기반으로 개발됨
  • 온프레미스 환경에서 상용 서비스의 쿠버네티스 클러스터를 구성할 때 유용함
  • 추가 구성 요소를 클러스터에 실행하는 역할 (ingress-nginx 컨트롤러, 헬름, 볼륨 플러그인, cert-manager 등)
  • kubespray에서 제공하는 고가용성 구조는 kubeadm과 다름 ==> 로그밸런서를 사용하지 않고 노드 각각의 nginx가 리버스 프록시로 실행됨
  • nginx-proxy가 전체 마스터 노드를 바라봄

 

[출처] https://www.bookstack.cn/read/kubespray/ha-mode.md

 

kubeadm

  • 쿠버네티스에서 공식 제공하는 클러스터 생성/관리 도구
  • 여러 대의 서버를 쿠버네티스 클러스터로 쉽게 구성할 수 있음
  • 고가용성을 제공하는 클러스터도 구성할 수 있음 ==> 워커 노드들이 마스터 노드에 접근할 때 로드밸런서를 거쳐 접근함

 

[출처] https://kubernetes.io/ko/docs/setup/production-environment/tools/kubeadm/ha-topology/

728x90
728x90

vagrant를 이용한 vm 준비


버추얼 박스 환경 설정

Virtualbox - 환경 설정

  • 입력 > 가상 머신 > 호스트 키 조합

 

  • 네트워크 > NatNetwork 확인

 

호스트 네트워크 관리자

  • 192.168.56.1/24

 


 

가상 머신 배포

운영 체제에 맞도록 vagrant 설치

https://www.vagrantup.com/

플러그인 설치

  • vagrant-hostmanager, vagrant-disksize
vagrant plugin install vagrant-hostmanager  
vagrant plugin install vagrant-disksize
vagrant plugin list

 

가상 머신 추가

  • ubuntu/bionic64 이미지를 이용한 가상 머신 추가
vagrant box add ubuntu/bionic64
vagrant box list

 

Vagrantfile 생성

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.define "kube-master1" do |config|
    config.vm.box = "ubuntu/bionic64"
    config.vm.provider "virtualbox" do |vb|
      vb.name = "kube-master1"
      vb.cpus = 2
      vb.memory = 3072
    end
    config.vm.hostname = "kube-master1"
    config.vm.network "private_network", ip: "192.168.56.11"
    config.disksize.size = "30GB"
  end
  config.vm.define "kube-node1" do |config|
    config.vm.box = "ubuntu/bionic64"
    config.vm.provider "virtualbox" do |vb|
      vb.name = "kube-node1"
      vb.cpus = 2
      vb.memory = 3072
    end
    config.vm.hostname = "kube-node1"
    config.vm.network "private_network", ip: "192.168.56.21"
    config.disksize.size = "30GB"
  end
  config.vm.define "kube-node2" do |config|
    config.vm.box = "ubuntu/bionic64"
    config.vm.provider "virtualbox" do |vb|
      vb.name = "kube-node2"
      vb.cpus = 2
      vb.memory = 3072
    end
    config.vm.hostname = "kube-node2"
    config.vm.network "private_network", ip: "192.168.56.22"
    config.disksize.size = "30GB"
  end
  config.vm.define "kube-node3" do |config|
    config.vm.box = "ubuntu/bionic64"
    config.vm.provider "virtualbox" do |vb|
     vb.name = "kube-node3"
      vb.cpus = 2
      vb.memory = 3072
    end
    config.vm.hostname = "kube-node3"
    config.vm.network "private_network", ip: "192.168.56.23"
    config.disksize.size = "30GB"
  end

  # Hostmanager plugin
  config.hostmanager.enabled = true
  config.hostmanager.manage_guest = true

  # Enable SSH Password Authentication
  config.vm.provision "shell", inline: <<-SHELL
    sed -i 's/ChallengeResponseAuthentication no/ChallengeResponseAuthentication yes/g' /etc/ssh/sshd_config
    sed -i 's/archive.ubuntu.com/ftp.daum.net/g' /etc/apt/sources.list
    sed -i 's/security.ubuntu.com/ftp.daum.net/g' /etc/apt/sources.list
    systemctl restart ssh
  SHELL
end

 

가상 머신 생성

  • Vagrantfile이 있는 경로에서 명령 실행
  • Vagrantfile에 정의된 내용으로 가상 머신 생성
  • 총 4대의 가상 머신 (마스터 노드 1대, 워커 노드 3대)
vagrant up

 

가상 머신 접속

  • kube-master1에 vagrant 사용자 계정으로 ssh 접속
  • 패스워드: vagrant
ssh vagrant@192.168.56.11
Password: vagrant

728x90
728x90

Docker Compose란


Docker Compose

여러 컨테이너를 모아 관리하는 툴

  • docker-compose.yml 파일에 컨테이너의 구성 정보를 정의하여 동일 호스트상의 여러 컨테이너를 일괄적으로 관리할 수 있음
  • compose 정의 파일은 웹 애플리케이션의 의존 관계를 모아서 설정할 수 있음
  • 정의 파일을 기반으로 docker-compose 명령을 실행하면 여러 개의 컨테이너를 모아서 시작하거나 정지할 수 있음
  • 컨테이너 구성 정보를 YAML 형식의 파일로 관리할 수 있음
  • CI/CD 프로세스에서 자동 테스트를 할 때 환경 구축에 그대로 이용할 수 있음

 


 

Compose 구성 파일 작성

Docker Compose는 구성 정보를 정의 파일에서 설정함

  • Compose 정의 파일 확인
  • 'webserver'와 'redis'라는 이름의 서비스 2개 정의
  • webserver 서비스는 커런트 디렉토리에 있는 Dockerfile에 정의한 구성의 이미지를 빌드( build: . )하고, 외부에 대해 80번 포트를 공개( port: )하여 컨테이너 시작
  • 컨테이너는 redis 서비스에 의존( depends_on: )함
  • redis 서비스는 Docker Hub에 공개되어 있는 Redis의 공식 이미지인 'redis'의 버전 4.0을 베이스 이미지( image: )로 하여 컨테이너 시작
[root@localhost compose]# cat docker-compose.yml
version: '3.3'
services:
  # WebServer config
  webserver:
    build: .
    ports:
      - "80:80"
    depends_on:
      - redis

  # Redis config
  redis:
    image: redis

 


 

Docker Compose 명령

주요 서브 명령

  • docker-compose 명령은 docker-compose.yml을 저장한 디렉토리에서 실행됨
명령 설명
up 여러 Docker 컨테이너 생성/시작
stop 여러 Docker 컨테이너 정지
down 리소스 삭제
ps 컨테이너 목록 표시
logs 컨테이너 로그 출력
run 컨테이너 실행
start 컨테이너 시작
restart 컨테이너 재시작
pause 컨테이너 일시 정지
unpause 컨테이너 재개
port 공개 포트 번호 표시
config 구성 확인
kill 실행 중인 컨테이너 강제 정지
rm 컨테이너 삭제

 


 

docker-compose.yml 작성

image: 이미지 지정

  • Docker 컨테이너의 베이스 이미지 지정
  • 이미지 이름 또는 이미지 ID 지정
  • 로컬 환경에 없는 경우 Docker Hub로부터 자동 다운로드
  • 태그를 지정하지 않는 경우 최신 버전 다운로드
services:
webserver:
    image: khj/imagetest:1.0 # 태그 지정 또는
    image: ubuntu # 태그를 지정하지 않음

 

 

build: 이미지 빌드

  • 이미지의 작성을 Dockerfile에 기술하고 자동 빌드하여 베이스 이미지로 지정할 때 사용
  • Dockerfile의 파일 경로 지정
  • docker-compose.yml 파일이 있는 디렉토리를 커런트 디렉토리로 했을 때 Dockerfile의 위치를 지정함
  • build 지정
sevices:
  webserver:
    build: .

 

  • Dockerfile 작성
FROM ubuntu

 

  • 컨테이너 생성
docker-compose up --build

 

 

  • Dockerfile과 컨텍스트 지정
  • /compose에 저장되어 있는 Dockerfile-com이라는 이름의 Dockerfile을 빌드함
  • 파일 경로는 상대/절대 모두 지정 가능
services:
  webserver:
    build:
      context: /compose
      dockerfile: Dockerfile-com

 

 

 

command/entrypoint: 컨테이너 안에서 작동하는 명령 지정

  • 컨테이너 안에서 작동하는 명령 지정
command: /bin/bash

 

  • entrypoint 지정
entrypoint:
  - php
  - -d
  - memory_limit=-1

 

 

ports/expose: 컨테이너 간 통신

  • 공개 포트 지정
ports:
  - "3000"
  - "8000:8000"
  - "49100:22"
  - "127.0.0.1:8001:8001"

 

  • 컨테이너 내부에만 공개하는 포트 지정
expose:
  - "3000"
  - "8000"

 

 

 

depends_on: 서비스의 의존 관계 정의

  • 주의: 컨테이너의 시작 순서만 제어할 뿐 컨테이너상의 애플리케이션이 이용 가능해질 때까지는 제어하지 않음

 

volumes/volumes_from: 컨테이너 데이터 관리

  • 컨테이너에 볼륨을 마운트할 때 사용
  • 볼륨 지정
volumes:
  - /var/lib/mysql
  - cache/:/tmp/cache

 

  • 읽기 전용 볼륨 지정 (ro)
volumes:
  - ~/configs:/etc/configs/:ro

 

  • 볼륨 마운트 지정
  • 다른 컨테이너로부터 모든 볼륨을 마운트할 경우 사용
  • log라는 이름의 컨테이너로 마운트
volumes_from:
  - log
728x90
728x90

실습 환경 리소스 정리


컨테이너 & 이미지 모두 삭제

도커 컨테이너 모두 삭제

  • 구동 중인 모든 컨테이너 중지, 삭제
docker stop $(docker ps -aq) 
docker rm $(docker ps -aq)

 

도커 이미지 모두 삭제

docker rmi $(docker images -q)

 

  • 에러 발생: IMAGE ID 가 동일하여 충돌이 일어나 삭제할 수 없음
  • Error response from daemon: conflict: unable to delete e66264b98777 (must be forced) - image is referenced in multiple repositories
  • 해결: 강제 삭제
docker rmi -f $(docker ps -aq)

 


 

Docker Registry를 사용한 프라이빗 레지스트리 구축


 

로컬 환경에 Docker 레지스트리 구축

  • Docker 레지스트리는 프라이빗 네트워크 안에서만 이미지를 공개할 수 있음
  • registry 검색
[root@localhost ~]# docker search registry
NAME                            DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
registry                        The Docker Registry 2.0 implementation for s…   3614      [OK]
~

 

  • registry 다운로드
[root@localhost ~]# docker image pull registry

 

  • registry 이미지 확인
[root@localhost ~]# docker image ls
REPOSITORY     TAG       IMAGE ID       CREATED       SIZE
registry       latest    773dbf02e42e   3 weeks ago   24.1MB

 

  • registry 컨테이너 시작
  • 레지스트리는 5000번 포트를 사용함
[root@localhost ~]# docker container run -d -p 5000:5000 --name registry registry
09ad150b0b06f7e8407ae64893b1f38189eda07af8507b0e857c85df2c5e91fc

 

  • registry 컨테이너 확인
[root@localhost ~]# docker container ls
CONTAINER ID   IMAGE      COMMAND                  CREATED              STATUS              PORTS                                       NAMES
09ad150b0b06   registry   "/entrypoint.sh /etc…"   About a minute ago   Up About a minute   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   registry

 

Docker 이미지 업로드

  • Dockerfile.base 베이스 이미지 작성 후 빌드
# Dockerfile.base 작성
[root@localhost Dockerfile]# vi Dockerfile.base

FROM ubuntu:16.04

RUN apt-get -y update && apt-get -y upgrade
RUN apt-get -y install nginx

EXPOSE 80

ONBUILD ADD website.tar /var/www/html/

CMD ["nginx", "-g", "daemon off;"]

# web-base 이미지 빌드
[root@localhost Dockerfile]# docker build -t web-base -f Dockerfile.base .

 

  • index.html 작성 후 tar 파일로 저장
[root@localhost Dockerfile]# vi index.html

<!doctype html>
<html>
  <head>
    <h1>Private Registry</h1>
  </head>
  <body>
    <img src="https://miro.medium.com/max/560/1*0DFwvFiEE0BiSG6hC8Q-8Q.png">
  </body>
</html>


[root@localhost Dockerfile]# tar -cvf website.tar index.html

 

  • Dockerfile 작성
[root@localhost Dockerfile]# vi Dockerfile

FROM web-base

 

  • webpage 이미지 빌드
[root@localhost Dockerfile]# docker build -t webpage .

 

  • webpage 이미지 태그 설정
  • 로컬 이미지명: webpage
  • localhost의 5000번 포트에서 작동
  • 레지스트리에 업로드할 이미지명: rg-webpage
  • webpage와 rg-webpage의 IMAGE ID는 동일함 => 동일한 이미지임을 알 수 있음
[root@localhost Dockerfile]# docker image tag webpage localhost:5000/rg-webpage

[root@localhost Dockerfile]# docker image ls
REPOSITORY                  TAG       IMAGE ID       CREATED          SIZE
webpage                     latest    38288fd45692   3 minutes ago    222MB
localhost:5000/rg-webpage   latest    38288fd45692   3 minutes ago    222MB

 

  • 이미지 업로드
[root@localhost Dockerfile]# docker image push localhost:5000/rg-webpage
~
sha256:d4013a81e4478edbc5cda16ee11e92fb556f95a3f155edaa00245c6ae2df29bc size: 1781

 

  • 로컬 이미지 삭제
[root@localhost Dockerfile]# docker image rm localhost:5000/rg-webpage:latest
[root@localhost Dockerfile]# docker image rm webpage

 

 

 

Docker 이미지 다운로드와 작동 확인

  • 프라이빗 레지스트리에서 이미지 다운로드
[root@localhost Dockerfile]# docker image pull localhost:5000/rg-webpage
~
sha256:d4013a81e4478edbc5cda16ee11e92fb556f95a3f155edaa00245c6ae2df29bc
Status: Downloaded newer image for localhost:5000/rg-webpage:latest
localhost:5000/rg-webpage:latest

 

 

  • 이미지 목록 표시
[root@localhost Dockerfile]# docker image ls
REPOSITORY                  TAG       IMAGE ID       CREATED          SIZE
localhost:5000/rg-webpage   latest    38288fd45692   10 minutes ago   222MB

 

  • 작동 확인
  • 웹 브라우저에서 localhost IP:80로 접속
[root@localhost Dockerfile]# docker container run -d -p 80:80 localhost:5000/rg-webpage
d50b9e8f1baa1bfbb41cac59ffd20308f3760e781045891819710f96943be16c

 

  • 웹 브라우저에서 localhost IP:8888로 접속
[root@localhost Dockerfile]# docker container run -d -p 8888:80 localhost:5000/rg-webpage
c39e04736962f7c5ece162681557d5123e25c9fd69420bd4e44cf0371fcbf429

728x90
728x90

파일 설정


ADD: 파일 및 디렉토리 추가

이미지에 호스트상의 파일이나 디렉토리를 추가할 때 사용

ADD <호스트 파일 경로> <Docker 이미지 파일 경로>ADD ["<호스트 파일 경로>" "<Docker 이미지 파일 경로>"]

  • 호스트상의 파일이나 디렉토리, 원격 파일을 Docker 이미지 안으로 복사

 

  • 호스트 상의 host.html 파일을 이미지 안의 /docker_dir/에 추가
  • Dockerfile이 있는 경로에 host.html 파일 생성
# host.html 파일 생성
[root@localhost Dockerfile]# touch host.html
[root@localhost Dockerfile]# ls
Dockerfile  Dockerfile.base  host.html  index.html  website.tar

 

 

  • Dockerfile 작성
[root@localhost Dockerfile]# vi Dockerfile
FROM centos:7

ADD host.html /docker_dir/

 

  • add 이미지 빌드
[root@localhost Dockerfile]# docker build -t add .
Sending build context to Docker daemon  15.36kB
Step 1/2 : FROM centos:7
 ---> eeb6ee3f44bd
Step 2/2 : ADD host.html /docker_dir/
 ---> Using cache
 ---> 8d416c2d5b91
Successfully built 8d416c2d5b91
Successfully tagged add:latest

 

 

  • 생성한 add 이미지를 이용한 컨테이너 실행
[root@localhost Dockerfile]# docker run -it add

 

  • 실행된 컨테이너의 /docker_dir/ 경로에서 복사된 host.html 파일 확인
[root@0f90594633cd /]# ls /docker_dir/
host.html

 


 

COPY: 파일 복사

이미지에 호스트상의 파일이나 디렉토리를 복사할 때 사용

COPY <호스트 파일 경로> <Docker 이미지 파일 경로>

COPY ["<호스트 파일 경로>" "<Docker 이미지 파일 경로>"]

  • ADD 명령과 유사함
  • ADD 명령: 원격 파일의 다운로드나 아카이브 압축 해제 등과 같은 기능이 있음
  • COPY 명령: 호스트상의 파일을 이미지 안으로 복사하는 처리만 함

 


 

VOLUME: 볼륨 마운트

이미지에 볼륨 할당

VOLUME ["/마운트 포인트"]

  • 지정한 이름의 마운트 포인트 작성
  • 호스트나 그 외 다른 컨테이너로부터 볼륨의 외부 마운트를 수행함
  • 영구 데이터 저장이 필요한 경우 컨테이너 밖의 Docker의 호스트 머신상의 볼륨이나 공유 스토리지 볼륨에 마운트하여 사용
  • ==> 컨테이너는 영구 데이터를 저장하는 데 적합하지 않음
  • 설정 가능한 값
# JSON 배열
VOLUME ["/var/log/"]

# 또는
VOLUME /var/log

# 여러 개의 인수로된 문자열
VOLUME /var/log /var/db
728x90
728x90

환경 및 네트워크 설정


ENV: 환경 변수 설정

key value 형식: ENV [key] [value]

  • 단일 환경 변수에 하나의 값 설정
  • ENV 명령이 3줄에 걸쳐있으므로 3개의 Docker 이미지를 겹쳐서 만듦
ENV myName "jinkim"
ENV myOrder Gin Whisky Calvados
ENV myNickName jin

 

key=value 형식: ENV [key]=[value]

  • 한 번에 여러 개의 값 설정
  • 하나의 ENV 명령으로 여러 개의 값을 설정하므로 하나의 Docker 이미지 생성
ENV myName="jinkim" \
    myOrder=Gin \ Whisky \ Calvados \
    myNickName=jin

 


 

WORKDIR: 작업 디렉토리 지정

Dockerfile에서 정의한 명령을 실행하기 위한 작업용 디렉토리 지정을 위해 사용

  • RUN, CMD, ENTRYPOINT, COPY, ADD 명령을 실행하기 위해 작업용 디렉토리를 지정함
  • 지정한 디렉토리가 없다면 새로 생성
  • WORKDIR 명령은 Dockerfile 안에서 여러 번 사용 가능

 

  • 절대 경로/상대 경로 사용 
  • 실행 결과: /first/second/third 출력
WORKDIR /first
WORKDIR second
WORKDIR third
RUN ["pwd"]

 

  • WORKDIR 명령으로 환경 변수 사용
  • 실행 결과: /first/second 출력
ENV DIRPATH /first
ENV DIRNAME second
WORKDIR $DIRPATH/$DIRNAME
RUN ["pwd"]

 


 

USER: 사용자 지정

이미지 실행 또는 Dockerfile의 RUN, CMD, ENTRYPOINT 명령 실행을 위한 사용자 지정 시 사용

  • 첫 번째 whoami 명령은 root 사용자
  • 두 번째 whoami 명령은 jin 사용자
RUN ["adduser", "jin"]
RUN ["whoami"]
USER jin
RUN ["whoami"]

 

  • 실행 결과
[root@localhost Dockerfile]# docker build -t user .
Sending build context to Docker daemon  14.85kB
Step 1/5 : FROM centos:7
 ---> eeb6ee3f44bd
Step 2/5 : RUN ["adduser", "jin"]
 ---> Using cache
 ---> ab3430ec1ddd
Step 3/5 : RUN ["whoami"]
 ---> Running in 32bd59d818a1
root
Removing intermediate container 32bd59d818a1
 ---> b88098a6410e
Step 4/5 : USER jin
 ---> Running in 55417d12e8af
Removing intermediate container 55417d12e8af
 ---> 78cdbeeb3385
Step 5/5 : RUN ["whoami"]
 ---> Running in 9a5b3f43a654
jin
Removing intermediate container 9a5b3f43a654
 ---> 04802c29f8a7
Successfully built 04802c29f8a7
Successfully tagged user:latest

 


 

EXPOSE: 포트 설정

컨테이너의 포트 번호를 지정할 때 사용

  • Docker에게 실행 중인 컨테이너가 listen하고 있는 네트워크를 알려줌
  • docker container run 명령의 -p 옵션을 사용할 때 어떤 포트를 호스트에 공개할지 정의
  • 8080 포트 공개
EXPOSE 8080

 


 

ARG: Dockerfile 내 변수 설정

Dockerfile 안에서 사용할 변수를 정의할 때 사용

  • ARG 명령을 사용하면 변수의 값에 따라 생성되는 이미지의 내용을 변경할 수 있음
  • 환경 변수 ENV와 달리 ARG는 Dockerfile 안에서만 사용 가능
ARG YOURNAME="jin"
RUN echo $YOURNAME

 

  • ARG 명령 실행 결과
  • YOURNAME: JIN
[root@localhost Dockerfile]# docker build .
Sending build context to Docker daemon  14.85kB
Step 1/3 : FROM centos:7
 ---> eeb6ee3f44bd
Step 2/3 : ARG YOURNAME="JIN"
 ---> Running in 95fabeaddad3
Removing intermediate container 95fabeaddad3
 ---> bfa21b4abbd7
Step 3/3 : RUN echo $YOURNAME
 ---> Running in 90896b892b65
JIN
Removing intermediate container 90896b892b65
 ---> 09ac20e3d14d
Successfully built 09ac20e3d14d

 

  • --build-arg 옵션 사용
  • YOURNAME: KIM
[root@localhost Dockerfile]# docker build . --build-arg YOURNAME=KIM
Sending build context to Docker daemon  14.85kB
Step 1/3 : FROM centos:7
 ---> eeb6ee3f44bd
Step 2/3 : ARG YOURNAME="JIN"
 ---> Using cache
 ---> bfa21b4abbd7
Step 3/3 : RUN echo $YOURNAME
 ---> Running in 3fdd25c33b99
KIM
Removing intermediate container 3fdd25c33b99
 ---> 4fd9c9b92486
Successfully built 4fd9c9b92486

 


 

SHELL: 기본 쉘 설정

쉘 형식으로 명령을 실행할 때 기본 쉘 설정 시 사용

  • Linux 기본 쉘: ["/bin/sh", "-c"]
  • Windows 기본 쉘: ["cmd", "/S", "/C"]
# 기본 쉘 지정
SHELL ["/bin/bash", "-c"]

# RUN 명령 실행
RUN echo hello

 

  • 실행 결과
[root@localhost Dockerfile]# docker build .
Sending build context to Docker daemon  14.85kB
Step 1/3 : FROM centos:7
 ---> eeb6ee3f44bd
Step 2/3 : SHELL ["/bin/bash", "-c"]
 ---> Running in 99c03fb1a0fe
Removing intermediate container 99c03fb1a0fe
 ---> db4c37552f10
Step 3/3 : RUN echo hello
 ---> Running in 975a1c534dca
hello
Removing intermediate container 975a1c534dca
 ---> fc68001a93ec
Successfully built fc68001a93ec
728x90
728x90

명령 및 데몬 실행


RUN: 명령 실행

- 컨테이너에는 FROM 명령에서 지정한 베이스 이미지에 대해 '애플리케이션/미들웨어 설치 및 설정', '환경 구축 위한 명령 실행' 등과 같은 명령 실행 시 사용

- 이미지를 작성하기 위해 실행하는 명령 기술

Shell 형식

  • 쉘에서 실행
  • Shell 형식의 RUN 명령
# nginx 설치
RUN apt-get install -y nginx

 

Exec 형식

  • 쉘을 경유하지 않고 직접 실행
  • 환경 변수 지정 불가 (ex. $HOME 등)
  • 쉘 이용을 원할 경우 RUN 명령에 쉘 경로 지정
  • Exec 형식의 RUN 명령
# nginx 설치
RUN ["/bin/bash", "-c", "apt-get install -y nginx"]

 

  • RUN 명령의 실행 예
  • 문자열을 인수로 지정할 때는 ' (홑따옴표) 사용
  • RUN 명령은 Dockerfile에 여러 개 기술
# 베이스 이미지 설정
FROM ubuntu:latest

# RUN 명령 실행
RUN echo 안녕하세요 Shell 형식입니다
RUN ["echo", " 안녕하세요 Exec 형식입니다 "]
RUN ["/bin/bash", "-c", "echo ' 안녕하세요 Exec 형식에서 bash를 사용해 보>았습니다' "]

 

 

  • RUN 명령의 실행 로그
  • Dockerfile 은 명령 한 줄마다 이미지를 생성함
[root@localhost Dockerfile]# docker build -t run-test .
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM ubuntu:latest
 ---> 27941809078c
Step 2/4 : RUN echo 안녕하세요 Shell 형식입니다
 ---> Running in d44b834efa8a
안녕하세요 Shell 형식입니다
Removing intermediate container d44b834efa8a
 ---> dcf3550fd766
Step 3/4 : RUN ["echo", " 안녕하세요 Exec 형식입니다 "]
 ---> Running in 52f6c3ebf053
 안녕하세요 Exec 형식입니다
Removing intermediate container 52f6c3ebf053
 ---> 7b00dfbd8e60
Step 4/4 : RUN ["/bin/bash", "-c", "echo ' 안녕하세요 Exec 형식에서 bash를 사용해 보았습니다' "]
 ---> Running in da4e2d292bb7
 안녕하세요 Exec 형식에서 bash를 사용해 보았습니다
Removing intermediate container da4e2d292bb7
 ---> dcc5b8101c6b
Successfully built dcc5b8101c6b
Successfully tagged run-test:latest

 

  • 이미지 구성
  • 이미지를 생성할 때 어떤 명령이 실행되는지 확인
[root@localhost Dockerfile]# docker history run-test
IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
dcc5b8101c6b   4 minutes ago   /bin/bash -c echo ' 안녕하세요 Exec 형식에서…            0B
7b00dfbd8e60   4 minutes ago   echo  안녕하세요 Exec 형식입니다                          0B
dcf3550fd766   4 minutes ago   /bin/sh -c echo 안녕하세요 Shell 형식입니다               0B

 


 

CMD: 데몬 실행

- 이미지를 바탕으로 생성된 컨테이너 안에서 명령 실행 시 사용

- Dockerfile에는 하나의 CMD 명령만 기술 가능, 여러 개 지정 시 마지막 명령만 유효

Exec 형식

  • 쉘을 호출하지 않음
  • nginx를 포어그라운드에서 실행
CMD ["nginx", "-g", "daemon off;"]

 

Shell 형식

  • nginx를 포어그라운드에서 실행
CMD nginx -g 'daemon off;'

 

ENTRYPOINT 명령의 파라미터로 기술

  • ENTRYPOINT 명령의 인수로 CMD 명령을 사용할 수 있음
# 베이스 이미지 설정
FROM ubuntu:16.04

# Nginx 설치
RUN apt-get -y update && apt-get -y upgrade
RUN apt-get -y install nginx

# 포트 지정
EXPOSE 80

# 서버 실행
CMD ["nginx", "-g", "daemon off;"]

 

  • Docker 이미지 작성
[root@localhost Dockerfile]# docker build -t cmd-test .

 

  • 컨테이너 실행
[root@localhost Dockerfile]# docker container run -p 80:80 -d cmd-test
5d35e96603b8f7b61a3b9b8b95978e6d7610bbc66854a2598412694c8083e09e

[root@localhost Dockerfile]# docker ps
CONTAINER ID   IMAGE       COMMAND                  CREATED         STATUS        PORTS                                       NAMES
5d35e96603b8   cmd-test    "nginx -g 'daemon of…"   3 seconds ago   Up 1 second   0.0.0.0:80->80/tcp, :::80->80/tcp           bold_jepsen

 

 


 

ENTRYPOINT: 데몬 실행

- ENTRYPOINT에서 지정한 명령은 Dockerfile에서 빌드한 이미지로부터 Docker 컨테이너를 시작하기 때문에 docker container run 명령 실행 시 실행됨

Exec 형식

  • nginx를 포어그라운드에서 실행
ENTRYPOINT ["nginx", "-g", "daemon off;"]

 

Shell 형식

  • nginx를 포어그라운드에서 실행
ENTRYPOINT nginx -g 'daemon off;'

 

  • ENTRYPOINT 명령과 CMD 명령 조합
  • ENTRYPOINT 명령: 실행하고자 하는 명령 자체 지정
  • CMD명령: 그 명령의 인수 지정
  • ENTRYPOINT 명령으로 TOP 명령 실행, CMD 명령으로 갱신 간격인 -d 옵션을 10초로 지정
  • 이 이미지로부터 작성된 컨테이너는 top 명령이 반드시 실행되는데, 이 때 CMD 명령에서 지정한 옵션을 사용하여 실행 시의 인수를 임의로 docker container run 명령 실행 시로 지정할 수 있음
# 베이스 이미지 설정
FROM ubuntu:16.04

# top 실행
ENTRYPOINT ["top"]
CMD ["-d", "10"]

 

  • 이미지 작성
[root@localhost Dockerfile]# docker build -t ent-cmd .

 

  • 컨테이너 생성 및 실행
# CMD 명령에서 지정한 10초 간격으로 갱신하는 경우
[root@localhost Dockerfile]# docker container run -it ent-cmd

 

  • CMD 명령은 docker container run 명령 실행 시 덮어 쓸 수 있는 구조 때문에 가능함
# 2초 간격으로 갱신
[root@localhost Dockerfile]# docker container run -it ent-cmd -d 2

 


 

ONBUILD: 빌드 완료 후 실행되는 명령

- 다음 빌드에서 실행할 명령을 이미지 안에 설정하기 위한 명령

- Dockerfile로부터 생성한 이미지를 베이스 이미지로 한 다른 Dockerfile을 빌드할 때 실행

- 웹 시스템 구축 시 OS 설치 및 환경 설정, 웹 서버 설치 및 각종 플러그인 설치 등과 같은 인프라 환경 구축과 관련된 부분을 베이스 이미지로 작성

- 인프라 구축 관련 이미지와 애플리케이션 전개 관련 이미지 생성을 나누어 실행

- 이 때, ONBUILD 명령으로 이미지 안에 개발한 프로그램을 전개하는 명령(ADD, COPY 등) 지정

  • 1. 베이스 이미지 작성(Dockerfile.base)
# 베이스 이미지 설정
FROM ubuntu:17.10

# Nignx 설치
RUN apt-get -y update && apt-get -y upgrade
RUN apt-get -y install nginx

# 포트 지정
EXPOSE 80

# 웹 콘텐츠 배치
ONBUILD ADD website.tar /var/www/html/

# Nginx 실행
CMD ["nginx", "-g", "daemon off;"]

 

  • 베이스 이미지 빌드
  • Dockerfile을 Dockerfile.base라는 이름으로 지정하여 빌드 (-f 옵션 사용)
  • web-base라는 베이스 이미지가 생성됨
[root@localhost Dockerfile]# docker build -t web-base -f Dockerfile.base .

 

  • 2. 웹 콘텐츠 개발
  • Dockerfile이 있는 디렉토리에서 index.html 파일 생성 후 website.tar 파일로 압축
[root@localhost Dockerfile]# vi index.html
<!doctype html>
<html>
  <head>
    <h1>ONBUILD</h1>
  </head>
  <body>
    <img src="https://3.bp.blogspot.com/-rAve4gA0DNY/WzYXGT3G3aI/AAAAAAAABak/YGC8oM_TMsYDi9ZX8G6iEXgsag728eixgCLcBGAs/s400/Docker%2BONBUILD%2BCommand%2BExplained%2Bwith%2BExamples.jpg">
  </body>
</html>

[root@localhost Dockerfile]# tar -cvf website.tar index.html
index.html

[root@localhost Dockerfile]# ls
Dockerfile  Dockerfile.base  index.html  website.tar

 

  • 3. 웹 서버용 이미지 작성
# Docker 이미지 취득
FROM web-base

 

  • 웹 서버용 이미지 빌드
  • webpage라는 도커 이미지 생성
[root@localhost Dockerfile]# docker build -t webpage .
Sending build context to Docker daemon  14.85kB
Step 1/1 : FROM web-base
# Executing 1 build trigger
 ---> 3a4fd07273fc
Successfully built 3a4fd07273fc
Successfully tagged webpage:latest

 

 

  • 4. 웹 서버용 컨테이너 시작
[root@localhost Dockerfile]# docker container run -d -p 80:80 webpage
8b7f0e59a5d8cbfb08e9eb457c6fb9e8b077dcb4326e774a0f1ed687a4697809

 

  • 웹 브라우저에서 접속하여 확인 (enp0s8)

 

728x90
728x90

Dockerfile 빌드


docker build -t [생성할 이미지명]:[태그명] [Dockerfile의 위치]

Dockerfile로부터 이미지 생성

  • Dockerfile 생성
# test 디렉토리에 Dockerfile 생성
[root@localhost ~]# mkdir test
[root@localhost ~]# cd test
[root@localhost test]# touch Dockerfile
[root@localhost test]# ls
Dockerfile

 

  • Dockerfile 내용
[root@localhost test]# cat Dockerfile
FROM centos:centos7

 

  • docker build 실행
  • test: 이미지명
  • 1.0: 태그명
  • /root/test: Dockerfile이 위치한 경로
[root@localhost ~]# docker build -t test:1.0 /root/test
Sending build context to Docker daemon  2.048kB
Step 1/1 : FROM centos:centos7
centos7: Pulling from library/centos
Digest: sha256:c73f515d06b0fa07bb18d8202035e739a494ce760aa73129f60f4bf2bd22b407
Status: Downloaded newer image for centos:centos7
 ---> eeb6ee3f44bd
Successfully built eeb6ee3f44bd
Successfully tagged test:1.0

[root@localhost ~]# docker image ls
REPOSITORY     TAG       IMAGE ID       CREATED        SIZE
test           1.0       eeb6ee3f44bd   9 months ago   204MB

 

  • 이미지 확인
[root@localhost ~]# docker image ls
REPOSITORY     TAG       IMAGE ID       CREATED        SIZE
test           1.0       eeb6ee3f44bd   9 months ago   204MB

 

베이스 이미지가 로컬에 저장되어 있는 경우 이미지 생성

  • 두 번째 이후는 베이스 이미지를 Docker 레지스터에서 다운로드 하지 않음
[root@localhost ~]# docker build -t test:2.0 /root/test
Sending build context to Docker daemon  2.048kB
Step 1/1 : FROM centos:centos7
 ---> eeb6ee3f44bd
Successfully built eeb6ee3f44bd
Successfully tagged test:2.0

 

  • 이미지 확인
  • 베이스 이미지와 작성한 두 개의 이미지의 IMAGE ID가 동일함 > 이름은 다르지만 모두 동일한 이미지임을 알 수 있음
[root@localhost ~]# docker image ls
REPOSITORY     TAG       IMAGE ID       CREATED        SIZE
centos         centos7   eeb6ee3f44bd   9 months ago   204MB
test           1.0       eeb6ee3f44bd   9 months ago   204MB
test           2.0       eeb6ee3f44bd   9 months ago   204MB

 


 

멀티 스테이지 빌드


Docker 멀티 스테이지 빌드란?

컨테이너 이미지를 만들면서 빌드 등에는 필요하지만 최종 컨테이너 이미지에는 필요 없는 환경을 제거할 수 있도록 단계를 나누어 베이스 이미지를 만드는 방법

  • Dockerfile 빌드

[출처] https://www.metricfire.com/blog/how-to-build-optimal-docker-images/

 

  • 멀티 스테이지 빌드
  • 하나의 Dockerfile을 실행하여 빌드 이미지와 실행 이미지 분리가 가능해짐
  • 배포 이미지의 용량 감소, 빌드 시간 감소
  • 보다 가벼운 크기의 컨테이너 생성

[출처] https://www.metricfire.com/blog/how-to-build-optimal-docker-images/

 

728x90

+ Recent posts