💻 Frontend

Nginx file serving, Docker 컨테이너 배포

date
Oct 10, 2022
slug
docker
author
status
Public
tags
Docker
summary
Nginx file serving, Docker 컨테이너 배포
type
Post
thumbnail
docker.png
category
💻 Frontend
updatedAt
Apr 12, 2023 01:16 PM
 
[목차]
 

1. What is Docker

도커는 독립된 어플리케이션을 패키징하는 컨테이너이다.
이 말을 이해하기 위해서는 도커 컨테이너는 무엇인지
어플리케이션을 패키징한다는 것은 무엇이고, 어떤 방식으로 패키징해서, 어떻게 공유할 수 있는지 살펴보자.

1-1) Container? Docker Container?

notion image
우선 도커를 이해하는데 가장 중요한 컨테이너라는 개념을 살펴보자.
컨테이너는 어떤 환경에서나 실행하기 위해 필요한 모든 요소를 포함하는 고립된(isolated) 소프트웨어 패키지이다. 즉, 컨테이너안에는 어플리케이션을 실행할 수 있는 모든 파일(package, config 등)이 있다.
이 때 저마다의 OS(window, linux 등)가 컨테이너를 읽을 수 있게 세팅해줘야하는데, 이 세팅을 하는 것이 Container Engine이다.
이렇게 컨테이너 엔진 및 컨테이너 중 가장 대표적인 것이 Docker Engine과 Docker Container이다.
 

부록) 굉장히 많은 부연설명들

Docker = 컨테이너 아닌가? 컨테이너에 다른 종류도 있나?
네! docker외에 다른 컨테이너도 있습니다.
음.. 가상환경을 만든다는 것 같은데, VM이랑 똑같은 건가?
notion image
VM의 구조
notion image
Container의 구조
VM과는 명확한 차이점이 있는데, 바로 독립된 환경에서 OS 설치 유무이다. VM같은 경우에는 개별 가상환경별로 설정한 Guest OS를 설치한다.
반면 Container는 Container Engine을 통해 OS 설치 없이 실행 환경을 구성한다.
이 핵심적인 차이가 VM보다 Container가 빠르고, 확장성에서 유연하다는 장점을 만들어준다.
리눅스가 컨테이너를 읽는 방식 (아주아주 간단 ver)
도커는 리눅스에 내장되어있는 기술들을 활용해서 구현이 되었다.
리눅스에는 아래와 같은 격리 환경을 구축하기 위한 명령어를 수행할 수 있음.
notion image
 
아 복잡하네! 그래서 정리좀 해줘봐
notion image
도커로고가 이를 잘 표현하고 있음.
notion image
 

1-2) 그래서 Docker 왜 쓰는 거야?

Docker가 주목받는 핵심 요인은 도커 컨테이너를 세팅하면 어디서든 동일한 환경에서 개발을 할 수 있다.
이를 통해 아래와 같은 장점을 가질 수 있다.
 
A) 다양한 환경에서 협업을 하기 용이해진다 (Feat. Docker-hub)
B) 개별 환경에 대한 컨트롤이 편리해진다(dev,product)
C) Front,Back,DB 컨테이너들을 합치는 것도 수월해진다. (Feat. Docker-compose)
 

2. Docker Container 활용하기

컨테이너가 무엇인지와 장점을 살펴봤으니, 실제로 Docker Container를 어떻게 사용하는지 알아보자.
 
notion image
 
도커 컨테이너는 위와 같이 4가지 단계로 나뉘어서 실행할 수 있다.
  1. Dockerfile 빌드 및 image 생성
  1. image 파일을 push해서 등록한다.
  1. 컨테이너에서 image 파일을 가져온다.
  1. 컨테이너에서 어플리케이션을 실행한다.
 

2-1) Docker 설치하기

Install
notion image
notion image
 
 
 

2-2) Dockerfile 생성하기

도커파일이란? 컨테이너를 어떻게 만들어야할지에 대한 설명서라고 보면 된다.
도커파일에서 어플리케이션 파일을 복사,디펜던시 설치, 환경변수 설정, 구동하기 위한 명령어 설정이 가능하다.
notion image

도커파일 작성법

도커파일은 여러가지 문법을 통해서 작성이 가능한데, 기본적인 문법은 아래와 같다.
도커파일 작성시 위에서부터 아래로 해석하기 때문에 먼저 선행되거나, 수정사항이 가장 작은 것부터 위에서 적어야한다.
도커파일 예제
notion image

FROM node:16-alpine AS build 
# FROM을 통해 공식 이미지로 이미지의 뼈대를 만든다. 이것을 Base Image라고 함
# node 같은 프레임워크를 갖고 가면 최적화된 크기와 Linux 배포판이므로 Alpine 이미지 권장


WORKDIR /app
# WORKDIR을 통해 /app 폴더안에 워크디렉토리를 만들겠다는 것.


COPY package.json
COPY . .
# 특정 파일을 복사하고 싶을 때 COPY 명령어 사용
# node-modules를 전부 카피하고 싶을 때는 . . 을 붙이면 된다.

RUN npm install
RUN npm ci
# package.json에 있는 모든 파일을 install한다.
# 이때 npm install하면 최신 버전으로 다운로드 된다.
# 현재 파일 버전 그대로 다운로드 받기를 원한다면 npm ci를 할 수 있다.


EXPOSE 80

CMD ["npm","run","serve"]

ENV 
 
 

2-3) Image 만들고 push하기

An image is a read-only template with instructions for creating a Docker container.
Image란, 어플리케이션의 구성요소(Dockerfile)을 포함해서 snapshot해서 정적인 상태로 들고 있다.
template 형태로 이미지를 구성하고 있다.
notion image
# 터미널에 아래와 같이 입력하면 됨.
# 아래 명령어의 의미는 build from(Dockerfile) to(fun-docker)
# . 파일을 찍으면 dockerfile의 경로를 현재 경로에서 오픈한다는 것이다.

docker build -f Dockerfile -t fun-docker . 

#docker images로 현재 image의 상태를 확인할 수 있다.
docker images 
notion image
notion image
 

2-4) 이미지 컨테이너에 연결 및 실행하기

이미지를 실행시키면 컨테이너가 만들어지고 실행할 수 있다.
docker run -d -p 8080:8080 fun-docker
# -d stands for detached (to run a container in a background)
# -p is port publishing (maps a port on the container to a port on the host)

docker ps 
# 도커 현재 상태 알아보기
notion image
notion image
 
 

3. Nginx를 통해 Server 만들기 with Docker

3-1) What is nginx?

nginx는 웹 서버 소프트웨어이다
1) HTTP Server로 정적 파일을 Serveing
2) Reverse Proxy Server로서 Client와 Server 중개
notion image
개념 추가설명
1) HTTP Serve로 정적 파일을 Serveing해준다.
클라이언트(유저)로부터 요청을 받았을 때 WAS(API server)를 거치지 않고 요청에 맞는 정적 파일을 응답해주는 HTTP server로서 활용할 수 있다.
HTML, CSS 같은 정적인 리소스에 대한 요청을 Nginx가 처리해준다.
Vue의 build 된 파일들도 정적인 리소스라고 볼 수 있고 따라서 Nginx가 index.html 같은 메인 페이지를 랜더링 해줄 수 있다.
 
2) Reverse Proxy Server로서 Client와 Server 중개
Reverse Proxy Server로서 Client의 Request와 Server의 Response를 중개하는 서버로 동작하게 할 수 있다. 이 과정에서 nginx는 로드밸런서로서의 역할을 수행할 수 있다.
동적으로 계산되거나 전달되어야 하는 사항들은 WAS에게 맡긴다.
 
3) 로드밸런싱
서버의 부하(Load)를 분산(Balancing)시키는 기술이다.
많은 클라이언트들(이용자들)이 하나의 웹 사이트에 접속해서 해당 서버의 트래픽이 늘어날 때 여러 대의 서버를 이용해서 요청을 처리하도록 한다. 각 서버의 부하량, 속도 저하 등을 고려해서 서버의 가중치, 스케줄링 등을 결정해 트래픽을 적절히 분산시키는 과정을 로드밸런싱이라고 한다.
 
4) Apache vs Nginx
 

3-2) docker로 nginx 설정하기

도커파일에 Nginx 설치

코드
# STEP2. CREATE NGINX SERVER

# nginx Base Image로 설치하기
FROM nginx:1.23.3-alpine AS prod-stage
# dist 폴더 파일을 nginx html 경로에 copy하기
COPY --from=build /app/dist /usr/share/nginx/html
# 80 포트로 export 하기
EXPOSE 80
# nginx 실행하기
# CMD는 컨테이너 안에서 명령 실행. 하나의 Dockerfile에서 하나의 CMD만 명령 기술
CMD ["nginx", "-g", "daemon off;"]

nginx.conf 설정

코드
user  nginx;

# worker_processes는 발생하는 이벤트를 처리하는 프로세스의 수를 정의하는 지시어이다.
# 일반적으로 CPU의 core 수만큼 할당하고, auto로 설정하면 자동으로 값을 알맞게 설정해준다.
worker_processes  auto;

# nginx의 error_log가 쌓이는 경로
error_log  /var/log/nginx/error.log notice;

# nginx의 프로세스 아이디 (pid)가 저장되는 경로이다.
pid        /var/run/nginx.pid;


# worker_connections : 
# worker Process가 동시에 처리할 수 있는 접속자의 수를 나타낸다. 
# 기본은 1024로 설정되어져 있다.
events {
    worker_connections  1024;
}


http {
		#include : 포함시킬 외부파일을 정의함.
    include       /etc/nginx/mime.types;

		#웹 서버의 기본 content-type을 정의함
    default_type  application/octet-stream;

		#로그 형식을 지정한다.후술한 로그 형태에 따라 로그가 작성되고 기록됨
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

		# 접속 로그가 쌓이는 경로
    access_log  /var/log/nginx/access.log  main;

		# sendfile() 함수의 사용여부
    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

		#conf.d 폴더 안의 .conf 외부파일 읽음
    include /etc/nginx/conf.d/*.conf;
}

default.conf 설정

코드
server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}
 

3-3) shell script 활용한 build

shell script를 활용하면 변수 선언을 통해 Image_name 변수 설정 및 터미널 명령어를 한 번에 적용할 수 있어 편리함.
나중에는 기존 docker image 파일 삭제 등도 한 번에 할 수도 있음.
image_name="onboarding_dev_server"

echo "#docker image build"

docker build -f Dockerfile -t ${image_name} . 

docker run -d -p 80:80 ${image_name}

3-4) build 결과

notion image
notion image
 
 

4. 클라우드 활용 배포 (AWS - Elastic Beanstalk)

Elastic Beanstalk이란?

AWS Elastic Beanstalk는 Java, .NET, PHP, Node.js, Python, Ruby, Go, Docker를 사용하여 Apache, Nginx, Passenger, IIS와 같은 친숙한 서버에서 개발된 웹 애플리케이션 및 서비스를 간편하게 배포하고 조정할 수 있는 서비스입니다.
 
notion image
배포 과정을 Elastic Beanstalk에서 처리하기 때문에 코드를 업로드하면
배포부터 EC2, 로드밸런싱, 오토 스케일링, 모니터링 설정을 Elastic Beanstalk 한곳에서 할 수 있고,
이후 과정을 Elastic Beanstalk가 자동으로 처리
 
배포과정
notion image
notion image
notion image
notion image
notion image
notion image
 
 

5. Docker 200% 활용법

5-1) Docker Hub 활용

Dockerhub는 image를 버전관리하고, Pull, Push 할 수 있는 툴이다.
github에서 git repo를 통해 코드를 관리하는 것처럼말이다.
사용법
notion image
notion image
notion image
#이미지 등록
docker tag 이미지이름:latest 도커헙아이디/레포지토리명:latest

#이미지 확인
docker images

#도커 로그인
docker login

#이미지 푸시
docker push 도커헙아이디/레포지토리명:latest
 

5-2) Docker Compose 활용

도커컴포즈란, 여러 개의 컨테이너로부터 이루어진 서비스 구축, 순서, 관계를 정의해서 한 번에 여러개의 컨테이너를 실행하는 기능. 즉, 프론트, 백엔드, DB 각각의 컨테이너를 한 컨테이너로 감싸는 것.
샘플코드
docker-compose.yml

services:
  frontend:
    image: awesome/webapp
    ports:
      - "443:8043"
    networks:
      - front-tier
      - back-tier
    configs:
      - httpd-config
    secrets:
      - server-certificate

  backend:
    image: awesome/database
    volumes:
      - db-data:/etc/data
    networks:
      - back-tier

volumes:
  db-data:
    driver: flocker
    driver_opts:
      size: "10GiB"

configs:
  httpd-config:
    external: true

secrets:
  server-certificate:
    external: true

networks:
  # The presence of these objects is sufficient to define them
  front-tier: {}
  back-tier: {}
docker-compose up
 

 
참고문서