728x90
반응형

도커 EXPOSE

  • Expose는 컨테이너에 오픈할 포트를 의미한다.
  • 즉 컨테이너에서만 열려있는 포트로, 동일한 도커 네트워크에 속해있지 않은 호스트나 외부에서 접근할 수 없다.

도커 PORT

  • Port는 EXPOSE 된 컨테이너의 포트를 호스트에 열어주는 것을 의미한다.
  • 앞의 포트는 호스트의 포트, 뒤의 포트는 컨테이너의 노출된 포트를 의미한다.
  • 즉 동일한 도커 네트워크에 속해있지 않더라도, hostIP와 해당 포트를 알고 있다면 컨테이너에 접근이 가능해 진다.
  • 컨테이너의 포트를 호스트와 연결시켜주는 것이므로, 컨테이너 포트와 동일할 필요가 없다
    • 이 말은 다시 말하면, 특정 포트(3306 / 5504 / 6379등) 만을 사용해야하는 어플리케이션에 대해 다양한 포트 번호를 호스트가 사용할 수 있게 되는 것이다.
    • 왜냐하면 특정 포트를 반드시 사용해야 한다는 제약은 컨테이너의 포트에만 적용될 수 있기 때문이다.
      • 3306만을 사용해야하는 mysql을 구동할 때, PORTS를 5587:3306으로 설정한다면 외부에서는 5587로 접근하지만 어플리케이션은 3306 포트를 사용하는 효과를 거둘 수 있는 것이다.
728x90
반응형
728x90
반응형

도커 네트워크

  • 도커 네트워크는 일종의 내부망 이다.
    • 각 컨테이너들은 독립적인 네트워크 망을 가진다.
    • 정확히는 분리된 네트워크를 가진다 -> IP를 나눈다는 의미
    • 때문에 각 컨테이너별로 호스트와는 다른 가상의 IP 주소를 가진다.
  • 도커 네트워크는 컨테이너가 끼리의 통신을 할 수 있는 범위라 말할 수 있을 것 같다.
  • 기본적으로 컨테이너가 구동되게 되면 해당 컨테이너에 대한 default_network가 생성된다.
    • 이렇게 되면 다른 네트워크의 컨테이너와 소통할 수 없기 때문에 도커 외부로 우회하여 소통해야한다.
    • 컨테이너끼리 소통하기 위해 외부로 나갔다 들어와야 하기 때문에 성능적으로 저하가 발생하고, 보안적으로도 문제가 생길 수 있다.
  • 그러나 동일한 네트워크에 속한 컨테이너들 끼리는, 컨테이너의 이름과 포트만으로 서로 통신이 가능하다.

컨테이너 구동 시 도커 네트워크 구성에 대해

  • 컨테이너 구동 시, 순차적으로 도커 내부 IP 부여
    • 일반적으로 172.~~ 으로 시작하더라
    • 순차적으로 IP를 부여하기 때문에, 컨테이너를 내렸다 다시 올리면 컨테이너 IP가 변동 될 수 있음
  • 도커 네트워크는 내부망이기에, 외부와 연결시켜야 함
    • 컨테이너 구동 시, 자동적으로 컨테이너 마다 호스트에 veth(Virtual Ethernet)라는 가상 네트워크 인터페이스를 생성함
    • 네트워크 관련 설정을 하지 않는다면 default0 브릿지를 사용함

Docker Bridge

  • 도커 브릿지는 호스트와 컨테이너를 잇는 라우팅 경로
    • 즉 쉽게 말하면, 각 컨테이너에 가상의 IP를 부여하는 공유기 역할

도커 네트워크 전체 조회

  • 현재 사용중인 도커 네트워크 리스트 조회
docker network ls
  • 도커 네트워크 세부사항 조회
docker network inspect 

도커 네트워크 설정

  • 도커 네트워크 설정
  • docker network create <네트워크 이름>

컨테이너 네트워크 설정

  • 같은 도커 네트워크에 해당하는 모든 컨테이너들은 서로 내부 통신이 가능함
    • 이미 db_mariadb 라는 컨테이너가 proxy라는 도커 네트워크 안에 구동되어 있다면
    • 지금 올리는 어플리케이션 컨테이너를 proxy라는 네트워크에 포함시킴으로 인해서, db_mariadb:3306 을 url로 잡으면 통신이 가능해짐
    • 같은 네트워크가 아니라면, 'HostIP:컨테이너 포트' 를 통해 접근할 수 있음
      • 문제는 컨테이너가 호스트에 포트를 열어둔게 아닌, 컨테이너 포트만 노출 시킨 상태라면 접근할 수 있는 방법이 없어짐
  • 컨테이너 네트워크 설정 - docker compose
    • external: 컨테이너 구동 시 새로운 네트워크를 사용할지에 대한 여부를 설정하는 것
      • true: 기존 도커 네트워크를 할당함
      • false: 새로운 도커 네트워크를 생성함
    services:
        app:
            // 컨테이너 설정
            networks:
                - proxy
    
    networks:
        proxy:
          # proxy라는 새로운 네트워크를 생성하는게 아닌, 기존의 proxy라는 네트워크를 사용한다는 의미
            external: true
  • 컨테이너 네트워크 설정 - Dockerfile
    docker run app_name --net proxy
728x90
반응형
728x90
반응형

계기

컨테이너를 구동하였을 때,
해당 컨테이너가 정상적으로 올라간 것으로 보였지만 로그를 확인하거나 exec 명령어로 컨테이너 내부에 접근하고자 했을 때 문제가 발생하고 있는 것을 확인한 적이 여러번 있었다.

때문에 컨테이너의 정상 여부(Health) 를 주기적으로 체크하며 모니터링 할 필요가 있다.

healthcheck 옵션

  • docker compose 설정
    • healthcheck 라는 설정을 함으로써 가능하다.
      • test: 헬스체크 시도 시에 실행할 동작을 정의한다. 단순 curl/wget 으로 요청을 날려볼 수 있고, CLI를 넣을 수도 있으며, 함수를 실행시킬 수도 있다.
      • interval: 말 그대로 체크 실행 주기를 의미한다.
      • timeout: 실행된 헬스체크 동작에 대한 리턴을 기다리는 시간(timeout)을 의미한다.
      • retries: 타임아웃이 걸려 체크 실패 시 재시도 횟수를 의미한다. 재시도까지 전부 실패하면 unhealthy 상태가 된다.
      • start_period: 컨테이너 구동을 기준으로, 헬스체크를 시작할 때까지의 시간을 의미한다. 처음 구동 시, 초기 세팅에 시간이 많이 걸리는 경우가 있기 때문
    • 상태값
      • 0 : healthy. 즉 건강한 상태이다.
      • 1 혹은 다른 숫자: unhealthy. 비정상적인 문제가 발생하고 있다.
services:
    app:
        expose:
            - ${APP_PORT}
        healthcheck:  
            // 헬스체크를 위해 실행할 함수
            test: curl --fail http://localhost:5000/ || exit 1  

            // REDIS 체크의 경우
            test: [ "CMD", "redis-cli", "--raw", "incr", "ping" ]

            // 체크 실행 주기
            interval: 40s 
            // 타임아웃 
            timeout: 30s  
            retries: 3  
            // 컨테이너 구동 후 체크 시작할 시점
            start_period: 60s
  • DockerFile 설정

    • 도커 파일 설정은 Dockerfile의 이미지 빌드 과정에 입력된다.
    • 이외 헬스 체크 주기 등의 옵션은 컨테이너 구동 시 입력한다.
    FROM asdcasdcas
    # ... 빌드 내용
    
    # 컨테이너에서 구동하는 어플리케이션의 /health 엔드포인트에 요청을 날리는 것이 헬스체크 방식이다.
    HEALTHCHECK CMD curl --fail http://localhost/health
    docker container run -d -p 8080:80 --health-interval 5s app_image/stable/latest

    결과

    • 헬스체크가 완료되면 아래처럼 보이게 된다.

주기 설정에 관하여

  • healthcheck 는 어찌 되었건 cpu 등 서버 리소스를 사용하기 때문에 적당한 주기(interval)로 실행시켜야 한다.
  • 또한 실제로 헬스체크 동작을 실행시켰을 때 받아올 수 있는 정도의 주기로 실행해야 한다.
    • 만약 헬스체크 대상 어플리케이션의 특정 함수 동작 주기가 1분인데, 10초마다 헬스체크를 한다면, 이는 자원 낭비일 것이다.
728x90
반응형
728x90
반응형

 

본 과정은 Ubuntu 20.04 를 기준으로 작성되었습니다.

도커 설치

 

운영체제 패키지 업데이트

 

sudo apt-get update

 

 

필수 요소 설치

 

sudo apt-get install \
  apt-transport-https \
  ca-certificates \
  curl \
  gnupg \
  lsb-release -y

 

 

도커 GPG 키 설치

 

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

 

 

Stable 버전 도커 설치

 

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

 

 

도커 엔진 설치

 

sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io -y

 

 

버전 확인

 

docker version

 

 

도커 컴포즈는 뭔데?

 

도커 컴포즈는 컨테이너 이미지를 빌드하고, 컨테이너 설정을 미리 할 수 있는 설계도이다.

빌드할 도커 파일을 설정하고, 컨테이너 이름 및 공개할 포트 번호, 네트워크 등을 미리 설정할 수 있다.

 

도커 컴포즈 설치

 

sudo curl -L "https://github.com/docker/compose/releases/download/v2.9.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

 

 

실행 권한 부여

 

sudo chmod +x /usr/local/bin/docker-compose

 

 

버전 확인

 

docker-compose --version

 

728x90
반응형

'데브옵스 devOps > Docker' 카테고리의 다른 글

[DOCKER] 도커 port / expose 에 대해  (1) 2024.10.21
[DOCKER] 도커 네트워크에 관하여  (0) 2024.10.18
[DOCKER] 헬스체크  (2) 2024.10.03
[Docker] 도커란?  (1) 2024.09.25
[Docker] Private 도커 허브와 크레덴셜  (7) 2024.09.24
728x90
반응형

 

도커는 리눅스의 격리 기술을 활용한 기술이다.

 

프로세스란?

프로세스? 프로세스가 무엇인가. 여기서 시작해야 도커에 대한 설명을 할 수 있겠다. 우리가 주로 컴퓨터에 설치하는 것들을 ‘프로그램‘이라고 한다. 카카오톡, 알약, 팟플레이어 등… 모든것이 프로그램이라고 할 수 있다. 하지만 프로그램은 설치되었다고 해서 실행되는 것이 아니다. 실행을 시켜야 그 프로그램을 사용할 수 있다. 정말 러프하게 설명하자면 ‘실행되고 있는 프로그램을 프로세스‘라고 한다. 조금 전문적으로 설명하자면 CPU가 작업을 처리하기 위해 ‘메모리에 올라가 있는 프로그램‘이라고 말할 수 있겠다.

 

그래서 프로세스가 도커랑 뭐?

자 이제 프로세스가 도커와 무슨 상관일까? 도커를 러프하게 설명하자면, 프로세스를 구동하고 있는 가상 머신이다. 오.. 그렇구나. 그런데 가상머신 VM과 도커랑 무슨 차이가 있길래 구별을 하는거냐? 이것 역시 러프하게 얘기하자면, VM은 모든 가상 머신에 각각 OS가 설치되어있다. 내 컴퓨터에 가상 머신이 4개가 돌아가고 있다 가정한다면, 4개의 컴퓨터가 하나의 컴퓨터 안에서 돌아가고 있다고 생각해도 무방하다. 때문에 무겁다. 하지만 도커는 호스트의 OS를 공유하기 때문에 가상머신에 비해 비교적 빠르고 가볍다.

 

도커의 구성 요소?

자 이제 그러면 도커를 구성하는 요소들에 대해 설명하겠다. 도커는 크게 호스트, 컨테이너로 구성된다. 호스트란 가상 머신을 지칭하는 거로, OS가 구동된다. 컨테이너는 이 호스트에서 하나 이상의 프로세스를 구동하고 있는 단위이다. 우리의 컴퓨터랑 똑같이 생각하면 이해가 빠를 것이다. 컴퓨터를 켜서 배경화면에 와서(호스트 접속) 프로그램을 실행하면(컨테이너 구동) 프로그램을 사용할 수 있다. 물론 이 예시에서 클라이언트는 빠졌지만.

 

도커를 이용하는 방법

그렇다면 도커 컨테이너를 구동시키기 위하여 어떻게 해야 할 것인가? 우선 도커 컨테이너는 이미지라는 것을 가져와 프로세스를 구동시킨다. 방법은 두가지가 있다. 첫번째는 Dockerfile을 통해 현재 로컬 호스트의 소스코드와 구동 환경들을 정적으로 이미지 빌드하여 사용하는 것이다. 이 경우 커스텀한 이미지를 만들어 사용할 수 있다는 장점이 있다. 두번째는 레지스트리에서 가져오는 것이다. 레지스트리가 무엇인가? 쉽게 말하자면 이미지를 온라인상에 업로드 한 저장창고 라고 생각하면 쉽다. 가장 대표적으로 도커 공식 레지스트리 docker hub가 있다.

728x90
반응형
728x90
반응형

 

본 글은 Ubuntu 20.04 를 기준으로 작성되었습니다.

 

도커 이미지 허브

도커 이미지는 빌드되어 정적인 상태로 관리된다. 때문에 저장장치에 이미지를 업로드하여 url을 통해 내려 받아 와 사용할 수 있다. 이른바 CI/CD 의 일종으로 볼 수 있을 것 같다. 그런데 개인적인 프로젝트나, 회사 내부 프로젝트일 경우 이미지는 내부에서 관리되어야 하고 유출되면 곤란하다. 때문에 도커 이미지 레지스트리 관리 오픈소스 툴인 harbor 를 이용해 이미지를 관리해 왔다.

 

보안

이미지를 업로드한 저장소에 접근하기 위해선 저장소 접근 권한을 통해 로그인을 해야 한다. 그런데 리눅스 기반의 운영체제에서 (다른 운영체제는 잘 모르겠다) docker login 명령어를 통해 접근하려고 하면, 로컬에 해당 민감정보가 저장되어 버린다는 끔찍한 문제점이 존재한다. 때문에 도커에서도 공식적으로 이러한 방식이 아닌 credential을 이용해 접근하라고 권고하고 있다.

 

Docker Credential

- [공식 레포지토리](https://github.com/docker/docker-credential-helpers

Credential은 로컬에 그대로 저장하는 것이 아닌, 암호화 시키고 사용할 때 인증을 해서 접근 권한을 가져와 사용할 수 있게 해 준다. 어떤 능력자 분이 설치하는 스크립트를 공유해 주셔서 이를 공유해본다.

 

- [스크립트 원문](https://geoffhudik.com/tech/2020/09/15/docker-pass-credential-helper-on-ubuntu/)

#!/bin/sh
# Sets up a docker credential helper so docker login credentials are not stored encoded in base64 plain text.
# Uses the pass secret service as the credentials store.
#
# If previously logged in w/o cred helper, docker logout <registry> under each user or remove ~/.docker/config.json.
#
# For Swarm use just run once on a manager.
# Script written for use on Ubuntu.
# Run elevated logged in as the target user.
# To remove cred helper:
#   - delete /usr/local/bin/docker-credential-pass
#   - remove '{ "credsStore": "pass" }' from ~/.docker/config.json
# Ensure executable in git:
# git update-index --chmod=+x path/docker-credentials.sh
if ! [ $(id -u) = 0 ]; then
   echo "This script must be run as root"
   exit 1
fi
# Install dependencies - jq more optional for existing varying configuration in ~/.docker/config.json.
apt update && apt-get -y install gnupg2 pass rng-tools jq
# Check for later releases at https://github.com/docker/docker-credential-helpers/releases
version="v0.6.3"
archive="docker-credential-pass-$version-amd64.tar.gz"
url="https://github.com/docker/docker-credential-helpers/releases/download/$version/$archive"
# Download cred helper, unpack, make executable, move it where it'll be found
wget $url \
    && tar -xf $archive \
    && chmod +x docker-credential-pass \
    && mv -f docker-credential-pass /usr/local/bin/
# Done with the archive
rm -f $archive
config_path=~/.docker
config_filename=$config_path/config.json
# Could assume config.json isn't there or overwrite regardless and not use jq (or sed etc.)
# echo '{ "credsStore": "pass" }' > $config_filename
if [ ! -f $config_filename ]
then
    if [ ! -d $config_path ]
    then
        mkdir -p $config_path
    fi
    # Create default docker config file if it doesn't exist (never logged in etc.). Empty is fine currently.
    cat > $config_filename <<EOL
{
}
EOL
    echo "$config_filename created with defaults"
else
    echo "$config_filename already exists"
fi
# Whether config is new or existing, read into variable for easier file redirection (cat > truncate timing)
config_json=`cat $config_filename`
if [ -z "$config_json" ]; then
    # Empty file will prevent jq from working
    $config_json="{}"
fi
# Update Docker config to set the credential store. Used sed before but messy / edge cases.
echo "$config_json" | jq --arg credsStore pass '. + {credsStore: $credsStore}' > $config_filename
# Output / verify contents
echo "$config_filename:"
cat $config_filename | jq
# Help with entropy to prevent gpg2 full key generation hang
# Feeds data from a random number generator to the kernel's random number entropy pool
rngd -r /dev/urandom
# To cleanup extras from multiple runs: gpg --delete-secret-key <key-id>; gpg --delete-key <key-id>
echo "Generating GPG key, accept defaults but consider key size to 2048, supply user info"
gpg2 --full-generate-key
echo "Adjusting permissions"
sudo chown -R $USER:$USER ~/.gnupg
sudo find ~/.gnupg -type d -exec chmod 700 {} \;
sudo find ~/.gnupg -type f -exec chmod 600 {} \;
# List keys
gpg2 -k
# Grab target key
key=$(gpg2 --list-secret-keys | grep uid -B 1 | head -n 1 | sed 's/^ *//g')
echo "Initializing pass with key $key"
pass init $key
# Image can't be found when Swarm attempts to pull later if a pass phrase is here.
echo "Do not set a passphrase for this step (*IMPORTANT*)"
pass insert docker-credential-helpers/docker-pass-initialized-check
# Optionally show password but mask ***
# pass show docker-credential-helpers/docker-pass-initialized-check | sed -e 's/\(.\)/\*/g'
echo "Docker credential password list (empty initially):"
docker-credential-pass list
echo "Done. Ready to test. Run: docker login <registry>"
echo "After login run: docker-credential-pass list; cat ~/.docker/config.json; pass show"

 

도메인 등록

도커 로그인을 진행해서 도메인을 등록한다.

sudo docker login <docker hub | registry address>
>>username:
>>password:
>> succeed

 

리스트 업

sudo docker-credential-pass list
>> {"example.com":"username"}

 

활성화

아래 명령어를 입력하면 위에서 인증 키를 생성할 때 입력한 패스워드를 입력할 수 있는 창이 뜰 것이다. 이후에 저장소에 접근하면 정상적으로 가능해진다.

sudo pass ls docker-credential-helpers/docker-pass-initialized-check
728x90
반응형

'데브옵스 devOps > Docker' 카테고리의 다른 글

[DOCKER] 도커 port / expose 에 대해  (1) 2024.10.21
[DOCKER] 도커 네트워크에 관하여  (0) 2024.10.18
[DOCKER] 헬스체크  (2) 2024.10.03
[Docker] 도커 및 도커 컴포즈 설치  (0) 2024.09.25
[Docker] 도커란?  (1) 2024.09.25

+ Recent posts