Docker를 활용해서 EC2에 내가 만든 서버 올려보기

박희주·2023년 4월 17일
0

1. Docker 설치하기

1-1. EC2 인스턴스에서 Docker 설치

  • SSH키 발급받아서 SSH로 인스턴스 실행하기(그냥 인스턴스에 들어가서 연결해서도 실행가능)

    # ssh키 파일인 pem이 위치한 경로에서 진행
    $ ssh -i "[발급 받은 ssh.pem]" ubuntu[생성된 인스턴스 주소]
  • Docker 설치하기(Ubuntu 기반)

    # ubuntu를 관리자 권한으로 실행
    $ sudo -s
    
    # docker 설치 전 업데이트 진행
    $ sudo apt-get update
    $ sudo apt-get upgrade
    
    # docker 설치에 필요한 패키지 설치
    $ sudo apt-get install apt-transport-https ca-certificates curl gnupg lsb-release
    
    # docker 공식 GPG키 추가
    $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
    
    # docker repository 생성
    $ echo "deb [arch=amd64 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
    
    # docker 엔진 설치
    $ sudo apt-get update
    $ sudo apt-get install docker-ce docker-ce-cli contianerd.io
    
    # docker 서비스 시작
    $ sudo systemctl start docker
    
    # docker 서비스 상태 확인
    $ sudo systemctl status docker
    
    # docker 설치 확인
    $ docker --version
    $ which docker

1-2. MacOS(Apple Silicon)에서 Docker 설치하기

💡 Docker 홈페이지에서 직접 Docker Desktop으로 설치해도 무방

  • brew로 Docker Desktop 설치하기
    $ brew install --cask docker
    • 위의 명령어를 실행하면 Applications에 Docker Desktop이 설치된다.
  • Docker 설치 확인하기
    $ docker --version
    # Docker version 20.10.24, build 297e128
    # 위 메세지가 나온다면 정상적으로 설치 완료
    # 혹은
    $ which docker
    # /usr/local/bin/docker
    # 도커가 설치된 위치가 찍혀 나온다면 정상적으로 설치 완료

2. Docker Image 생성해보기

2-1. 프로젝트 루트폴더에 Dockerfile 생성하기

# 베이스 이미지를 지정한다.
# 해당 프로젝트는 node16 버젼에서 구동되는 것으로 셋팅
FROM node:16-alpine

# 작업 디렉토리를 지정한다.
# 작업 디렉토리를 지정하면 그 이후 모든 명령어는 해당 디렉토리를 기준으로 작동한다. cd 명령와 동일
WORKDIR /usr/app

# build명령 중간에 호스트의 파일 또는 폴더를 이미지에 가져오는 과정
# ADD 명령문도 역할은 같지만 좀 더 강력하게 사용가능한 명령문
COPY package.json .
COPY yarn.lock .
COPY tsconfig.json .
COPY . .

# 새로운 레이어에서 명령어를 실행하고 새로운 이미지를 생성한다.
RUN node --version
RUN yarn --version

RUN yarn install
RUN yarn build

# Dockerfile의 빌드로 생성된 이미지에서 열어줄 포트를 의미한다.
# 컨테이너 생성시 -p 옵션의 컨테이너 포트 값으로 EXPOSE의 값을 적어줘야한다.
EXPOSE 4000
# CMD와 ENTRYPOINT두가지로 나뉘는데 자세한 내용은 아래에서 후술하겠다.
CMD ["yarn", "start"]
  • Dockerfile에서 사용되는 주요 명령어

    Dockerfile의 포맷은 INSTRUCTION arguments로 구성되어 있다.
    INSTRUCTION은 대소문자 상관없으나 대문자로 쓰는것이 관례이다.

    • FROM: 베이스 이미지
      • 어느 이미지에서 시작할건지를 의미
    • MAINTAINER: 이미지를 생성한 개발자의 정보(1.13.0 이후 사용 X)
    • LABEL: 이미지에 메타데이터를 추가(key-value 형태)
    • RUN: 새로운 레이어에서 명령어를 실행하고 새로운 이미지를 생성
      • RUN 명령을 실행할 때 마다 레이어가 생성되고 캐시된다.
      • docker run 명령어 사용시 —entrypoint 옵션으로 덮어쓰기 가능
    • WORKDIR: 작업 디렉토리를 지정한다. 해당 디렉토리가 없으면 새로 생성한다.
      • 작업 디렉토리를 지정하면 그 이후 명령어는 해당 디렉토리를 기준으로 동작한다.
      • cd 명령어와 동일하다.
    • EXPOSE: Dockerfile의 빌드로 생성된 이미지에서 열어줄 포트를 의미한다.
      • 호스트 머신과 컨테이너 포트 매핑시 사용된다.
      • 컨테이너 생성 시 -p 옵션의 컨테이너 포트 값으로 EXPOSE 값을 적어야한다.
    • USER: 이미지를 어떤 계정에서 실행하는지 지정
      • 기본적으로 root에서 해준다.
    • COPY / ADD: build 명령 중간에 호스트의 파일 또는 폴더를 이미지에 가져오는 것
      • ADD 명령문은 좀 더 파워풀한 COPY명령문으로 볼 수 있다.
      • ADD 명령문은 일반 파일 분만 아니라 압축파일이나 네트워크 상의 파일도 사용할 수 있다.
      • 이렇게 특수한 파일을 다루는게 아니라면 COPY명령문을 사용하는 것이 권장된다.
    • ENV: 이미지에서 사용할 환경 변수 값을 지정한다.
      • path, NODE_ENV 등
    • CMD / ENTRYPOINT: 컨테이너를 생성 및 실행 할 때 실행할 명령어
      • 보통 컨테이너 내부에서 항상 돌아가야하는 서버를 띄울 때 사용한다.
        • CMD
          • 컨테이너를 생성할 때만 실행(docker run)
          • 컨테이너 생성 시, 추가적인 명령어에 따라 설정한 명령어를 수정할 수 있다.
        • ENTRYPOINT
          • 컨테이너를 시작할 때마다 실행(docker start)
          • 컨테이너 시작 시, 추가적인 명령어 존재 여부와 상관없이 무조건 실행된다.

3. Docker 빌드하기(이미지 만들기)

Dockerfile이 작성 됐다면 아래와 같은 명령어로 이미지를 빌드 할 수 있다.

$ docker build -t [이미지이름:버젼] [Dockerfile이 위치한 경로]
# 혹은
$ docker build -t [{제작자|조직이름}]/이미지이름:버젼] [Dockerfile이 위치한 경로]
# 이미지 이름 앞에 제작자나 개발자, 조직이름 등 누가 이미지를 만들었는지 명시하는 방법도 있음
# 이러한 방식을 활용하면 Docker Hub에서 쉽게 검색이 가능하다.
  • 유의사항

    💡 특히 Apple Silicon계열의 ARM기반 맥북에서는 빌드할 때 기본적으로 ARM64 아키텍쳐로 빌드가 되는데 이를 EC2에서는 작동되지 않는다.
    AWS EC2는 기본적으로 AMD64를 지원하기 때문에 아키텍쳐를 별도로 맞춰서 빌드해야줘야 한다.

    # AMD64로 빌드할 때 아래와 같이 빌드옵션에 --platform을 명시해준다.
    $ docker build --platform linux/amd64 -t [이미지 이름:버젼] [Dockerfile이 위치한 경로]
    # 참고 사항: 빌드된 이미지의 아키텍쳐 확인하기
    $ docker inspect [imageID] | grep Architecture
    # "Architecture": "arm64"
    # AMD64로 빌드하고 위의 명령어로 아키텍쳐를 확인해보면 바뀌어서 나온다.
    # "Architecture": "amd64",

4. 빌드된 이미지를 Docker Hub에 올리기

3번의 과정을 통해서 빌드를 완료하게 되면 로컬에 이미지가 생성된다.
이 이미지를 개인적으로 활용한다고 하면 따로 Docker Hub에 올릴 필욘 없지만 EC2에 배포하기 위해선 Docker Hub에 올려야 한다.(Github Repository에 푸쉬하는 느낌)

  • 푸쉬하는 방법은 간단하다. Docker Hub계정에 로그인을 하고 이미지 이름을 그대로 푸쉬하면 끝
    # 로그인 하기
    $ docker login
    # Login with your Docker ID to push and pull images from Docker Hub.
    # If you don't have a Docker, ID head over to https://hub.docker.com to create one.
    # Username: [Docker Hub에 등록된 내 계정 이름]
    # Password: [비밀번호 입력]
    # Logging in with your password grants your terminal complete access to your account.
    # 푸쉬할 때는 아래와 같이 해주면 끝
    $ docker push [이미지이름:버젼]

5. 빌드된 이미지를 Pull 받기

Github처럼 Docker 이미지를 Hub에 푸쉬했다면 마찬가지로 Pull을 해서 다른 누군가가 내 이미지를 활용 할 수 있는데 이는 docker가 설치되어 있는 환경이라면 어디서나 내가 만든 이미지를 사용할 수 있다.
현재 EC2에서 내가 만든 서버 이미지를 가동 시킬 수 있도록 해보는것을 예시로 해보자
(EC2 인스턴스에 연결되어있고 로그인이 되어 있다는 가정 하에)

# pull도 마찬가지로 간단하게 가능
$ docker pull [이미지이름:버젼]

6. 생성한 이미지나 Pull받은 이미지를 컨테이너로 실행시키기

최종적으로 빌드된 이미지나 Pull 받은 이미지를 이제 실행시켜보자

6-1. 최초 실행

# -p 옵션은 해당 이미지로 들어오는 요청의 port 번호를 내가 제작한 Dockerfile의 EXPOSE와 일치시켜준다.
# --name 옵션은 실행되는 컨테이너의 이름을 명시해준다.
$ docker run -p 80:4000 --name [컨테이너의 이름] [이미지이름:버젼]

# http의 기본 port는 80
# https의 기본 port는 443

6-2. 중단 후 실행

  • 컨테이너를 중단했다가 다시 실행할 때는 start명령어를 활용한다.

    # start명령어를 실행할 때는 컨테이너의 ID를 기입한다.
    $ docker start [containerID]
    
    # ID를 확인하는 방법(실행중인 컨테이너)
    $ docker ps
    # ID를 확인하는 방법(실행/중단 된 모든 컨테이너)
    $ docker ps -a

7. .dockerignore 작성

.dockerignore 파일은 .gitignore파일 같다.
.dockerignore에 파일들을 명시하면 말그대로 docker가 빌드할 때 해당 파일들은 같이 빌드 되지않고 빌드 컨텍스트에서 아예 제외가 되버린다.
ADDCOPY명령어에 영향을 받지 않는 파일로 이해하면 된다.

  • 주로 node_modules나 .log파일들 빌드결과 파일(dist) 등 이미지에 필요하지 않는 파일명들을 명시했다.

참고자료

얕은 지식으로 글을 작성했습니다. 보완해야하거나 지적해주시는 부분은 항상 감사하게 받겠습니다.

profile
하나부터 열까지, 머리부터 발 끝까지

0개의 댓글