[42] Inception

숭글·2023년 6월 28일
0

도커와 가상머신

도커(Docker)와 가상머신(VM)은 애플리케이션의 배포와 실행을 위한 컴퓨팅 환경을 구축하는 데 사용되는 기술이다.

차이점

  1. 가상화 수준:
    • 가상머신: 가상머신은 호스트 운영체제 위에 게스트 운영체제를 실행하기 위해 하드웨어를 에뮬레이트한다다. 가상머신은 하이퍼바이저(hypervisor)라는 소프트웨어를 사용하여 게스트 운영체제를 격리시키고 리소스를 할당한다.
    • 도커: 도커는 호스트 운영체제 위에 컨테이너라는 격리된 환경을 생성한다. 도커는 호스트 운영체제의 커널을 공유하므로 가상머신보다 더 가볍고 빠르게 실행될 수 있다.
  2. 격리 수준:
    • 가상머신: 가상머신은 완전한 운영체제를 가상화하기 때문에 격리 수준이 높다. 각 가상머신은 독립된 운영체제 이미지, 커널 및 리소스를 가지고 있어 한 가상머신이 다른 가상머신에 영향을 미치지 않는다.
    • 도커: 도커 컨테이너는 호스트 운영체제의 리소스를 공유하면서 격리된 환경을 제공한다. 도커 컨테이너는 각각 독립된 파일 시스템과 프로세스 공간을 가지고 있으며, 리소스 제한 및 네트워크 격리 등의 기능을 사용하여 서로 간섭하지 않고 실행된다.
  3. 시작 속도:
    • 가상머신: 가상머신은 게스트 운영체제의 부팅 과정이 필요하므로 시작 속도가 상대적으로 느릴 수 있다.
    • 도커: 도커 컨테이너는 호스트 운영체제의 커널을 공유하고 이미지를 기반으로 생성되므로 시작 속도가 매우 빠르다.
  4. 이미지 관리:
    • 가상머신: 가상머신: 가상머신은 전체 운영체제 이미지를 사용하여 애플리케이션과 의존성을 패키징한다. 따라서 가상머신 이미지는 크고 운영체제의 전체 복사본을 포함하므로 관리 및 배포에 부담이 될 수 있다.
    • 도커: 도커 컨테이너는 작은 크기의 이미지를 사용하며, 애플리케이션과 그 의존성만 포함된다. 이미지는 레이어(layer)라는 개념을 사용하여 쉽게 공유, 버전 관리 및 배포할 수 있다.

도커는 가상머신보다 가볍고 효율적인 애플리케이션 실행 환경을 제공하며, 개발과 배포의 편의성을 높여준다는 장점이 있고, 가상머신은 더 강력한 격리와 다양한 운영체제 환경을 지원한다는 장점이 있다.

Docker

도커(Docker)는 애플리케이션을 컨테이너화하여 패키징, 배포, 실행할 수 있는 플랫폼다. 도커 컴포즈(Docker Compose)는 다중 컨테이너 도커 애플리케이션을 정의하고 관리하는 도구다.

  1. 도커:
    • 도커는 클라이언트-서버 아키텍처를 사용한다. 도커 클라이언트가 도커 데몬과 통신하여 도커 컨테이너의 빌드, 실행, 배포를 관리한다.
    • 도커 컨테이너는 가벼우며 격리된 환경으로, 애플리케이션과 그에 필요한 종속성을 포함다. 도커 이미지를 기반으로 생성되며, 도커 이미지는 읽기 전용 템플릿으로서 애플리케이션 실행에 필요한 모든 파일과 명령을 포함한다.
    • 도커 이미지는 도커 파일(Dockerfile)을 사용하여 생성된다. 도커 파일은 이미지의 구성, 종속성, 빌드 단계 등을 지정하는 텍스트 파일이다. 도커 파일은 기본 이미지를 정의하고 추가적인 레이어를 추가하며, 환경 변수를 설정하고 파일을 복사하며, 명령을 실행하는 등의 작업을 정의한다.
    • 도커 이미지는 도커 허브(Docker Hub)나 개인 레지스트리와 같은 저장소에 저장된다. 이미지를 레지스트리에서 가져오거나 자체 이미지를 레지스트리에 업로드할 수 있다.
    • 도커 컨테이너를 실행하기 위해 이미지의 인스턴스를 생성한다. 이 과정을 인스턴스화라고 한다. 각 컨테이너는 독립적인 파일시스템, 네트워크, 프로세스 공간을 가지고 있지만, 호스트 운영 체제 커널을 공유한다.
    • 도커는 컨테이너를 관리하기 위해 시작, 중지, 재시작, 스케일링, 모니터링 등의 기능과 명령을 제공한다.
  2. 도커 컴포즈:
    • 도커 컴포즈는 다중 컨테이너 도커 애플리케이션의 관리를 간편하게 해주는 도구다. "docker-compose.yml"이라는 단일 YAML 파일에서 여러 서비스(컨테이너)를 정의하고 구성할 수 있다.
    • docker-compose.yml 파일은 서비스, 종속성, 네트워킹, 볼륨 등 애플리케이션 실행에 필요한 서비스들과 관련된 설정을 기술한다. 각 서비스에 대해 컨테이너 이미지, 환경 변수, 포트, 볼륨 등의 설정을 지정할 수 있다.
    • 도커 컴포즈를 사용하면 단일 명령으로 전체 애플리케이션 스택을 시작, 중지, 재시작할 수 있다. 또한 서비스의 스케일링과 라이프사이클 관리를 용이하게 할 수 있다.
    • 도커 컴포즈는 정의된 서비스들을 위한 가상 네트워크를 생성하여 서비스들이 서로 통신할 수 있도록 한다. 서비스 이름을 DNS 별칭으로 사용하여 서로 통신할 수 있다. 또한 데이터 지속성을 위해 볼륨을 생성하고 관리할 수도 있다.
    • 도커 컴포즈를 사용하면 웹 서버, 데이터베이스, 캐시 시스템 등 복잡한 애플리케이션 아키텍처를 정의하고 이를 단일 단위로 관리할 수 있다.

도커와 도커 컴포즈는 컨테이너화를 통해 애플리케이션과 종속성을 포함하는 이식성이 좋고 격리된 환경을 제공함으로써 애플리케이션을 패키징하고 관리하는 강력한 조합이다. 도커 이미지와 컨테이너를 사용하여 애플리케이션을 간편하게 구축하고 실행할 수 있으며, 도커 컴포즈를 사용하여 다중 컨테이너 애플리케이션의 구성과 종속성을 관리할 수 있다.

  • docker-compose.yml을 작성하기 전 compose file document 를 정독했다..

    • docker-compose.yaml 와 docker-compose.yml 이 둘 다 있는 경우 compose.yaml파일을 선호한다.
  • 사용할 만한 element

    • service
      • depends_on : express the dependencies between containers, docker consider it when start up, shut down.
      • domainname
      • entrypoint
      • env_file : add environment variables, values set by ‘environment’ have precedence.
      • expose : define the port
      • extra_host : add hostname(like /etc/hosts for linux)
      • links : define the network links
      • network_mode, networks
        • when network_mode is set, networks is ignored, networks reference the top-level networks key
      • ports : exposes container port, port mapping must not be used with network_mode: host
      • read_only
      • restart
      • secrets : grant access to sensitive data
      • tty : configures service container to run with a tty
      • container_name : container name 지정
  • Compose file reference

    • target
      • target defines the stage to build as defined inside a multi-stage Dockerfile.

        # Dev-ready container - actual files will be mounted in
        FROM --platform=$BUILDPLATFORM base AS dev
        CMD ["mkdocs", "serve", "-a", "0.0.0.0:8000"]
        
        # Do the actual build of the mkdocs site
        FROM --platform=$BUILDPLATFORM base AS build
        COPY . .
        RUN mkdocs build

compose파일 내에서 이미지 이름 지정하는 법

  • build, image 를 같이 적으면 image로 설정해둔 이름으로 이미지를 생성한다.
    • image로 설정해둔 이름을 허브에서 먼저 찾는다. 없으면 로컬에 도커파일이 있는 지 찾은 후 있다면 이미지로 지정해둔 이름으로 이미지를 생성한다.
    • image : specific_name:tag 로 하면 된다.

Dockerfile 구성

  • FROM : base image
  • RUN : 실행할 코드
  • WORKDIR : 작업 디렉토리
    • 디렉토리가 존재하지않으면 생성한다.
  • COPY : 파일, 디렉토리 복사 COPY [origin][copyfile]
  • ENV : 환경 변수 지정
  • ENTRYPOINT : 컨테이너 실행할 때 실행하는 명령어
    • [’명령어’, ‘인자’, ‘인자’, …]

    • ENTRYPOINT ["/bin/bash"] 해서 실행시키면 컨테이너 환경에서 bash를 사용해볼 수 있다!

      docker run -it [image_name]
    • -i : iteractive

    • -t : tty

  • CMD
    • 컨테이너를 실행할때 디폴트를 제공한다.
      • 디폴트는 실행 파일을 포함하거나 생략할 수 있다.(param만 넣을 수 있음, 그런 경우엔 entrypoint도 지정해야한다.)
      • CMD ["executable","param1","param2"] (exec form, this is the preferred form)
      • CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
        • 이 경우에는 entrypoint를 지정해줘야함.
      • CMD command param1 param2 (shell form)

single Dockerfile build

docker build [--tag image_name]

run image

docker run [-옵션 .]
  • —rm : 컨테이너가 종료될 때 관련된 리소스를 제거해준다.
  • -it : interactice tty
    • entrypoint에 tty가 있을 경우 옵션으로 넣어야 tty에 접근할 수 있다.

container 죽이기

docker container kill [container id]
  • 한번에 다 죽이기
    docker rm -f $(docker ps -qa)
  • network 리스트 보는 법
    docker network ls
  • network 환경 보는 법
    docker network inspect [network 이름]

compose 사용을 안하면 빌드/실행시킬때마다 아래처럼 정보를 다 적어줘야한다..

docker run -d -p 80:80 -v ./app:/var/www/html nginx sleep infinity
docker run -d -p 9000:9000 -v ./app:/var/www/html wordpress sleep infinity
docker run -d --expose 3306 mariadb sleep infinity

expose, ports 차이

  • expose :

    • 호스트 내부에서 다른 컨테이너들에게 노출되는 포트 설정
  • ports:

    • 호스트 외부에서 접근 할 수 있는 포트 설정
      • -1:2 해두면 내부에서는 1로 접근 외부에서는 2로 접근
  • compose up 할 때 'not found' 에러 발생, 싱글 도커파일 빌드할 때는 잘 됐음

    • context가 build될때의 working directory가 됨. 경로가 안맞아서 찾을 수 없던 거였음. compose파일 service context에 알맞은 경로 입력해줌
      • context = a path to a directory containing a Dockerfile, or a url to a git repository.

Docker development best practices

Avoid storing application data in your container’s writable layer using storage drivers. This increases the size of your container and is less efficient from an I/O perspective than using volumes or bind mounts.

Start with an appropriate base image. For instance, if you need a JDK, consider basing your image on the official openjdk image, rather than starting with a generic ubuntu image and installing openjdk as part of the Dockerfile.

라고 돼있지만 서브젝트에서 이미지는 os만 허용해줘서 debian위에 쌓아야한다..

reduce the number of layers in your image by minimizing the number of separate RUN commands in your Dockerfile.

RUN apt-get -y update
RUN apt-get install -y python
RUN apt-get -y update && apt-get install -y python

밑 코드가 더 적은 layer를 쌓는다.

  • If you have multiple images with a lot in common, consider creating your own base image with the shared components, and basing your unique images on that.

볼륨 설정하는 4가지 방법

Mysql

mysql command line option

  • -h host
  • -u 아이디
  • -p 비밀번호

prompt로 쿼리 날리기

mysql -u [ID] -p [PW] < [FILENAME]

mysql query

  • create database [DB_NAME]
    • 데이터베이스 생성
  • show databases
    • 데이터베이스 목록
  • use [database_name]
    • 사용할 데이터베이스
  • show tables
    • 테이블 목록

mysqld = mysql + daemon = 백그라운드에서 실행되는 프로세스

(이것뿐만 아니라 d가 붙은 건 웬만하면 다 daemon이었다..)

Wordpress

웹사이트를 만들고 관리하기 위한 도구로 사용되는 오픈 소스 기반의 웹 콘텐츠 관리 시스템(Content Management System, CMS)이다.

PHP-FPM은 PHP FastCGI Process Manager의 약자로, PHP 언어를 실행하는 데 사용되는 프로세스 관리자입니다.

워드프레스(WordPress)는 PHP로 작성된 오픈소스 웹 콘텐츠 관리 시스템(CMS)이며, PHP-FPM은 워드프레스와 함께 사용되는 일반적인 실행 환경입니다. PHP-FPM은 FastCGI 프로토콜을 통해 웹 서버와 통신하여 PHP 파일을 처리합니다.

PHP-FPM은 워드프레스와 같은 동적인 웹 애플리케이션을 실행하기 위해 필요한 기능을 제공합니다. 이를 통해 PHP 코드를 처리하고 결과를 웹 서버에 반환하는 역할을 합니다. 또한, PHP-FPM은 웹 서버와 독립적으로 실행되며, 요청에 따라 자동으로 PHP 프로세스를 생성하고 관리하여 웹 애플리케이션의 성능과 확장성을 향상시킵니다.

워드프레스와 함께 PHP-FPM을 사용하면 웹 서버와 PHP 실행 환경을 분리하여 보다 효율적인 웹 애플리케이션 운영이 가능해집니다.

WordPress는 PHP와 MySQL을 기반으로 작동한다. PHP는 서버 측 스크립팅 언어로, 웹페이지를 동적으로 생성하고 데이터베이스와 상호작용하는 데 사용된다. MySQL은 데이터베이스 관리 시스템으로, 웹사이트의 내용과 설정을 저장한다.

  • wp-config.php 파일 생성
    • 내부에는 연결할 데이터베이스에 관한 정보가 적혀있다.
    • 직접 sample파일을 수정해서 복사하는 방법과 wp-cli를 이용해서 config파일을 생성하는 방법이 있다.
    • wp-cli이용하는 법
      • wp-cli를 이용해 core(wordpress)를 다운받는다.

        wp core download --path=${WP_PATH} --allow-root
      • 연결할 database의 정보를 전달하여 config파일을 생성한다.

        wp config create --dbname=${DB_NAME} --dbuser=${DB_USER_NAME} --dbpass=${DB_USER_PASSWD} --dbhost=${DB_HOST} --path=${WP_PATH} --allow-root --skip-check
      • url을 이용하여 database에 wordpress table을 생성한다.

        wp core install --url=${WP_URL} --title=${WP_TITLE} --admin_user=${ADMIN_NAME} --admin_password=${ADMIN_PASSWD} --admin_email=${ADMIN_EMAIL} --allow-root --path=${WP_PATH}
      • 새로운 유저를 생성한다.

        wp user create ${USER_NAME} ${USER_EMAIL} --user_pass=${USER_PASSWD} --allow-root --path=${WP_PATH}
    • —allow-root
      • root 사용을 허용한다.
    • --skip-check
      • 체크를 스킵한다.

Nginx

NGINX는 오픈 소스 웹 서버 소프트웨어이다.

  • 클라이언트와 웹 서버 사이에서 요청을 처리하는데 사용된다. 기본적으로 정적 파일의 서비스, 리버스 프록시, 로드 밸런싱 등의 기능을 수행한다. 또한, SSL/TLS 암호화, 가상 호스팅(Virtual Hosting), URL 리다이렉션, 압축, 캐싱 등 다양한 기능을 제공한다.

NGINX의 주요 특징

  1. 높은 성능: NGINX는 비동기 이벤트 기반 구조로 설계되어 많은 동시 연결을 처리할 수 있고, 리소스 사용을 최적화하여 높은 처리량과 낮은 지연 시간을 제공다.
  2. 확장성: NGINX는 다중 CPU 및 메모리 코어를 활용하여 수평 확장이 가능하며, 로드 밸런싱을 통해 부하 분산을 지원한다.
  3. 리버스 프록시: NGINX는 클라이언트 요청을 웹 서버로 전달하기 전에 뒷단 서버로 요청을 프록시하는 역할을 수행할 수 있다. 이를 통해 성능 향상, 보안 강화 및 애플리케이션의 유연한 구성이 가능하다.
  4. 가상 호스팅: NGINX는 단일 서버에서 여러 도메인을 호스팅할 수 있는 가상 호스팅 기능을 제공한다. 이를 통해 서버 자원을 효율적으로 활용할 수 있다.
  5. SSL/TLS 암호화: NGINX는 SSL/TLS 프로토콜을 지원하여 웹사이트의 통신을 암호화할 수 있다. 이를 통해 보안 강화와 데이터의 안전한 전송이 가능하다.

모듈화된 아키텍처를 가지고 있어 확장성과 유연성이 높다.

OpenSSL은 오픈 소스로 개발된 암호화 라이브러리입니다. OpenSSL은 SSL(보안 소켓 레이어) 및 TLS(전송 계층 보안) 프로토콜을 구현하고, 네트워크 통신에서 데이터의 기밀성과 무결성을 제공하기 위해 사용됩니다.

OpenSSL은 암호화, 복호화, 디지털 서명, 인증서 생성 및 관리 등 다양한 암호 기능을 제공합니다. 이러한 기능은 네트워크 통신, 웹 서버, 이메일 서버 등 다양한 보안 요구에 활용될 수 있습니다.

OpenSSL은 C 언어로 작성되어 있으며, 대부분의 유닉스 및 윈도우 운영 체제에서 사용할 수 있습니다. 또한 OpenSSL은 많은 애플리케이션과 시스템에서 기본적으로 사용되는 암호화 도구입니다. 예를 들어, 웹 서버인 Apache나 Nginx에서 SSL/TLS 암호화를 위해 OpenSSL을 사용합니다.

또한 OpenSSL은 커맨드 라인 도구로도 제공되어, 인증서 생성, 디지털 서명 검증, 암호화된 데이터의 복호화 등을 수행할 수 있습니다.

OpenSSL은 오픈 소스로 개발되었기 때문에 소스 코드를 검토하고 수정할 수 있으며, 안정성과 보안성을 높일 수 있습니다.

TLS

Transport Layer Security의 줄임말. TLS는 암호화와 인증을 통해 인터넷 통신의 보안을 제공하는 프로토콜이다. SSL(Secure Sockets Layer) 프로토콜의 후속 버전이다.

TLS는 웹사이트의 HTTPS(보안 HTTP) 연결에서 가장 널리 사용되는 프로토콜이다. 또한, 이메일 보호, VPN(Virtual Private Network) 연결, 메시징 애플리케이션 등 다양한 통신 프로토콜에서 사용되어 데이터의 보안성을 제공한다.

  1. 암호화: TLS는 데이터의 기밀성을 보장하기 위해 데이터를 암호화한다. 암호화는 데이터를 변조하거나 유출되는 것을 방지하여 제3자가 데이터를 볼 수 없도록 한다.
  2. 인증: TLS는 서버의 신원을 확인하여 클라이언트가 신뢰할 수 있는 서버와 통신하고 있는지 확인한다. 클라이언트와 서버 간의 상호 인증을 통해 중간자 공격과 같은 위험을 방지한다.
  3. 무결성 보호: TLS는 데이터의 무결성을 보장합니다. 데이터가 전송 중에 변조되지 않았는지를 검증하여 데이터의 무결성을 유지한다.
  4. 다양한 보안 기능: TLS는 다양한 보안 기능을 제공한다. 예를 들어, 공개키 인증서를 사용하여 서버의 신원을 확인하고 키 교환을 위한 다양한 프로토콜과 알고리즘을 지원한다.

/etc/nginx/nginx.conf? /etc/nginx/conf.d/default.conf?

conf파일을 어떤 이름으로 복사해야할까..

nginx.conf로 하면 event가 없다느니, http블록에 넣으라느니 여러 에러가 뜬다.

알고보니 이미 존재하는 nginx.conf에 필수로 있어야하는 부분이었고 내가 부족한 파일로 덮어씌워 없애버린거였다..!

파일 내부를 확인해보니 nginx/nginx.conf파일에서는 /etc/nginx/conf.d/*.conf 를 인클루드하고있었다.

그래서 내가 작성한 conf파일은 conf.d폴더 안에 아무이름으로 넣어주면 nginx.conf파일에 포함되게 된다.

맘편하게 이 방법을 사용했다.

Bash

chown a b

  • b파일의 소유권을 a 로 변경한다.

chown a:b c

  • c파일의 소유권을 a로 그룹은 b로 변경한다.

About pid 1

pid1의 역할

  • pid 1인 프로세스는 init process로 부팅 시 커널에 의해 최초로 생성되는 프로세스다.
    • 초기화 시스템에 책임이 있다.
  • 고아 프로세스가 생긴 경우에 init 프로세스는 해당 프로세스들을 adopt하여 거둬준다.
  • 도커를 사용할 때도 entrypoint로 명시된 프로세스를 pid 1로써 새로운 pid 네임스페이스에 정의한다.

docker 내부 프로세스가 pid 1 프로세스일 때 문제점

  • 하위 프로세스로 신호를 보낼 수 없는 프로세스일 때(ex. sh)
    • 프로세스가 완료될 때까지 종료될 수 없다. 컨테이너를 종료하기 위해서는 sigkill을 보내야 한다.
  • 내 프로세스가 pid 1인 경우
    • pid 1 이므로 신호를 수신해도 예상하는 응답이 나오지 않을 수 있다.

일반 프로세스들은 term 시그널에 대한 기본 동작으로 종료하기 전 clean up을 진행한다. 하지만 pid 1은 시그널 핸들러가 등록되어있지 않아 term에 어떠한 영향을 받지않는다. 시그널 핸들러를 등록해두지 않은 경우, 자식 프로세스가 하위 프로세스를 생성한 뒤 종료됐다면 고아 프로세스가 계속 생길 수 있다.

docker run이 systerm 을 수신하면 컨테이너가 죽지 않더라도 신호를 컨테이너로 전달할 후 종료되고, docker stop의, 경우 명령을 수신하면 term시그널을 보낸 후 10초를 기다린 다음 중지되지않으면 Kill을 전송하여 정리할 기회없이 즉시 중지된다.

이러한 문제를 해결하는 게 Dumb-init이다.

dumb-init을 사용하면 entrypoint로 등록한 프로세스가 pid 1이 아닌 dumb-init의 자식이 된다.

dumb-init은 모든 시그널에 대해 핸들러를 등록하고 해당 시그널을 프로세스 세션으로 전달한다. 등록한 프로세스는 pid 1이 아니라 term신호를 정상적으로 수신할 수 있게된다. dumb-init은 adopt도 하여 고아 프로세스를 거두는 역할도 하게된다.

profile
Hi!😁 I'm Soongle. Welcome to my Velog!!!

0개의 댓글