도커는 2021년 스택오버플로우 설문조사 기타 개발 도구 부문에서 Git 다음으로 2위를 차지하였을 만큼 많은 개발자들이 사용하고 있는 도구입니다.
76.5%의 사용자가 도커를 사랑하고 있고
29.7%의 개발자들이 도커를 사용해보고 싶어합니다.
container 라고 불리는 하나의 작은 소프트웨어 유닛 안에 어플리케이션과 그에 필요한 시스템 툴, 환경설정 등 모든 dependency 를 하나로 묶어서 다른 서버나 다른 PC, 어디에서나 쉽게 배포하고 안정적으로 구동할 수 있도록 도와주는 툴이다.
기술이 발전함에 따라 어플리케이션을 구동하는데 많은 것들이 필요해졌다.
node.js 를 예로 들면 소스파일만 서버에 배포하는 것으로는 구동하는데 문제점이 있다.
npm, 환경설정, 디펜던시들, 환경변수 등 모든 것들을 설치하고 설정해야 하는데, 서버마다, PC 마다 모든 것들을 설치하고 설정하는 것은 번거롭고 오류가 발생하기도 쉽다.
이런 번거로움을 해결하기 위해 docker 가 탄생했다.
도커의 컨테이너에는 어플리케이션을 구동하는데 필요한 모든 것들을 담아 놓았다.
VM 은 하드웨어 위에 vmware 나 VirtualBox 와 같은 하이퍼바이저 소프트웨어를 이용하여 가상 머신을 만드는 것이다.
한 운영체제 위에서 동일한 어플리케이션을 각각 고립된 다른 환경에서 구동하기 위해서는 이 VM 을 이용하여 어플리케이션을 구동해야 했다.
VM 은 각각의 운영체제를 포함하고 있기 때문에 Mac 위에서 사용하면 Window 와 Linux 를 동시에 구동할 수 있다.
하지만 VM 을 사용하면 운영체제를 포함하고 있기 때문에 굉장히 무겁고 컴퓨터의 리소스를 많이 사용하게 된다.
Container 는 VM 에서 조금 경량화 된 컨셉입니다.
Container 는 하드웨어에 설치된 운영체제인 Host OS 에서 Container Engine 이라는 소프트웨어를 설치하면 각각의 고립된 container 를 만들어서 어플리케이션을 고립된 환경에서 구동할 수 있게 해줍니다.
container 는 운영체제를 포함하지 않고 container engine 이 설치된 host OS 를 공유한다.
container 가 구동되기 위해서는 container engine 이 필요하고 이 container engine 들 중에 가장 많이 사랑 받는 것이 Docker
무엇이 필요한지 적혀있는 파일
-> 설명서, 요리의 레시피
dockerfile 을 이용해 만든, 변경이 불가능한 image 파일
-> 객체지향의 Class
템플릿 형태로 이미지를 만들어두고 그 이미지를 이용하여 실제로 어플리케이션이 동작하는 container 를 만들 수 있다.
image 를 따라 만든 고립된 실행 환경
-> sandbox
Git, Github 와 비슷한 방식으로 작동한다.
npm init -y
프로젝트 초기화
npm install express
express 설치
index.js
const express = require('express')
const app = express()
app.get('/', (req, res) => res.send('This is Docker 🐳'))
app.listen('8080', () => console.log('✅ Server is running'))
Dockerfile 은 기본적으로 다음과 같은 명령문이 겹겹이 쌓인 layer 형태로 구성되어 있다.
# 주석 (Comment)
명령어 (INSTRUCTION) 인자 (arguments)
각 명령어는 모두 대문자로 작성하며 여러개의 인자가 따라올 수 있다.
주석 또한 달 수 있다.
base image
node 의 경우 미리 만들어 둔 node base image 가 있다.
FROM <base image:version>
: 뒤에 오는 숫자는 버전을 의미하며, alpine 은 최소의 linux 버전을 말한다.
FROM ubuntu:lastes
FROM node:16-alpine
WORKDIR
명령어는 리눅스 명령어 cd
처럼 container 상에서 작업 디렉토리를 전환하기 위해 사용한다.
WORKDIR <경로>
WORKDIR /app
COPY
명령어는 host PC 의 파일을 Docker image 의 파일 시스템으로 복사하기 위해 사용합니다.
절대경로와 상대경로를 모두 사용할 수 있으며, 상대경로를 사용하는 경우 이전에 WORKDIR
명령어로 전환된 현재 위치를 고려해야 한다.
Dockerfile 에서 명령어를 수행할 때 레이어 시스템으로 구성되므로 빈번히 변경되는 파일일수록 제일 마지막에 작성하는게 좋다.
COPY <파일> <경로>
COPY package.json ./
파일 중 소스코드를 담고 있는 index.js
가 디펜던시에 대한 정보를 담고 있는 package.json
이나 package-lock.json
보다 빈번히 변경되므로 제일 나중에 복사한다.
RUN
은 실행 명령어 입니다.
RUN <커맨드>
npm install
을 사용하면 최신 버전이 설치되어 버전이 달라질 수 있기 때문에 개발 시 사용한 정확한 버전을 설치하도록 package-lock.json
을 참고하는 npm ci
를 사용하는 것이 좋다.
RUN npm install <패키지>
ENTRYPOINT
명령어는 이미지가 컨테이너로 만들어져 실행될 때 항상 실행되어야 하는 커맨드를 지정합니다.
ENTRYPOINT <커맨드>
ENTRYPOINT npm start
Dockerfile 은 layer 형태로 작성하는 것이 좋다.
제일 빈번히 변경되는 것일수록 제일 마지막에 작성하여 레이어 제일 위쪽에 위치하게 한다.
그러면 이후 소스파일이 변경되어 새로운 image 를 만들어야 할 때, 변경된 레이어만 변경하고 나머지는 재사용 할 수 있어 image 를 빌드하는데 더 효율적이다.
FROM node:16-alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY index.js .
ENTRYPOINT ["node", "index.js"]
docker build -f Dockerfile -t my-first-docker .
.
build context
최상위 경로에 Dockerfile 이 있다.-f
, --file
Dockerfile
이라고 작성하지만 다른 이름을 지정할 수 있다.-t
, --tag
Dockerfile 에 작성한대로 순차적으로 실행되는 것을 볼 수 있다.
docker images
명령어를 사용하면 생성된 image 파일을 볼 수 있다.
REPOSITORY
github의 repository 와 동일하며, container 에 올릴 때 이 이름을 재사용하게 된다.
TAG
image 버전을 따로 지정하지 않았기 때문에 default 값인 lastest 이다.
docker run -d -p 8080:8080 my-first-docker
-d
, --detach
container 가 백그라운드에서 실행되고 있게 한다.
node.js 백엔드 어플리케이션이기 때문에 terminal 이 기다리지 않도록 detach 해준다.
-p
, --publish
<host 의 포트>:<container 의 포트>
constainer 는 고립된 환경에서 동작하므로 host 의 포트와 container 의 포트를 연결한다.
docker ps
명령어로 실행중인 container 의 리스트를 확인할 수 있다.
localhost:8080 으로 들어가보면...
docker logs <container id>
container 에서 발생하고 있는 터미널 메세지 (로그) 를 확인할 수 있다.
docker tag
image 파일의 이름을 변경한다.
Docker hub에서 새로운 repository 를 만들면, Docker commands 에 어떻게 image 를 push 할 수 있는지 알려준다.
docker push <docker 계정>/<repository 이름>:<태그>
tag
명령어를 사용하여 만들었던 image 의 이름을 docker 계정을 넣어 새롭게 만들어 준다.
docker login
명령어를 사용하여 로그인한다.
docker push moonshadow95/my-first-docker:latest
push 완료!