이번 기회에 Docker를 사용할 기회가 있어서 도커를 처음 접해봤다. Docker에 대해 기록해보려 한다.
Docker란?
- 어플리케이션의 실행에 필요한 환경을 하나의 이미지로 모아두고, 그 이미지를 사용하여 다양한 환경에서 어플리케이션 실행환경을 구축 및 운용하기 위한 컨테이너 기반의 오픈소스 플랫폼이다.
컨테이너(Container)
- Docker를 이해하는데 있어서는 그 배경에 있는 컨테이너 기술이 어떤 것인지를 알아야 한다.
- 컨테이너란 호스트 OS 상에 논리적인 컨테이너를 만들고, 어플리케이션을 작동시키기 위해 필요한 라이브러리나 어플리케이션 등을 하나로 모아, 마치 별도의 서버인 것처럼 사용할 수 있게 만드는 것이다. 호스트 OS의 리소스를 논리적으로 분리시키고, 여러개의 컨테이너가 공유하여 사용한다. 컨테이너는 오버헤드가 적기 때문에 가볍고 고속으로 작동하는 것이 특징이다.
이미지(Image)

- 이미지는 컨테이너 실행에 필요한 파일과 설정 값 등을 포함하고 있는 것으로 상태값을 가지고 변하지 않음(Immutable).
- 컨테이너는 이미지를 실행한 상태라 볼 수 있고 추가되거나 변하는 값은 컨테이너에 저장된다. 같은 이미지에서 여러개의 컨테이너를 생성할 수 있고 컨테이너의 상태가 바뀌거나 컨테이너가 삭제되더라도 이미지는 변하지 않고 그대로 존재한다.
👉🏻 이미지는 컨테이너를 실행하기 위한 모든 정보를 가지고 있기 대문에 더이상 의존성 파일을 컴파일하고 이것저것 설치할 필요가 없다! 새로운 서버가 추가되면 미리 만들어놓은 이미지를 다운받고 컨테이너만 생성하면 된다.
Docker Layer
- 도커의 이미지가 변할때마다 새롭게 다운 받으면 이미지의 용량이 크기에 비효율적이다.이를 해결하기 위해 Layer라는 개념을 이용한다.
- 기존 이미지에 추가적인 파일이 필요할때 다시 다운 받는 방법이 아닌 해당 파일을 추가하기 위한 개념이다.
- 이미지는 여러 개의 읽기 전용 레이어로 구성되고 파일이 추가되거나 수정되면 새로운 레이어가 생성된다.

- Ubuntu 이미지가 A+B+C이 집합이라면, ubuntu 이미지를 베이스로 만든 nginx 이미지는 A+B+C+nginx가된다. webapp 이미지를 nginx 이미지 기반으로 만들었다면 예상대로 A+B+C+nginx+source 레이어로 구성된다. webapp 소스를 수정하면 A,B,C,nginx 레이어를 제외한 새로운 source(v2)레이어만 다운받으면 되기 때문에 굉장히 효율적으로 이미지를 관리할 수 있다.
- 컨테이너를 생성할때도 레이어 방식을 사용하는데 기존의 이미지 레이어 위에 읽기/쓰기 레이어를 추가한다. 이미지 레이어를 그대로 사용하면서 컨테이너가 실행중에 생성하는 파일이나 변경된 내용은 읽기/쓰기 레이어에 저장되므로 여러 개의 컨테이너를 생성해도 최소한의 용량만 사용한다. 가상화의 특성상 이미지 용량은 크고 여러대의 서버에 배포하는 걸 감안하면 단순하지만 엄청나게 영리한 설계이다.
이미지 경로

- 이미지는 URL 방식으로 관리하며 태그를 붙일 수 있다. ubuntu 14.04이미지는 docker.io/library/ubuntu:14.04 또는 docker.io/library/ubuntu:trusty 이고 docker.io/library는 생략 가능하며 ubuntu:14.04로 사용할 수 있다. 이러한 방식은 이해하기 쉽고 편리하게 사용할 수 있으며 태그 기능을 잘 이용하면 테스트나 롤백도 쉽게 할 수 있다.
Docker File이란?
- Docker Image를 만들기 위한 설정 파일이다. 여러가지 명령어를 토대로 Docker File을 작성하면 설정된 내용대로 Docker Image를 만들수 있다.

FROM
- base 이미지를 지정해주기 위해서 사용되는데, 보통 Dockerfile 내에서 최상단에 위치하게 된다. base 이미지는 일반적으로 Docker Hub와 같은 Docker repository에 올려놓은 잘 알려진 공개 이미지인 경우가 많다.
- Ubuntu 최신 버전을 base 이미지로 사용
FROM ubuntu:latest
VOLUME
- 디렉터리의 내용을 컨테이너에 저장하지 않고 호스트에 저장하도록 설정한다.
데이터볼륨을 호스트의 특정 디렉터리와 연결하려면 docker run 명령에서 -v 옵션을 사용해야 한다.
EXPOSE
EXPOSE <포트>
EXPOSE <포트> /</프로토콜>
- 네트워크 상에서 컨테이너로 들어오는 트래픽(traffic)을 리스닝(listening)하는 포트와 프로토콜를 지정하기 위해서 사용된다. 프로토콜은 TCP와 UDP 중 선택할 수 있는데 지정하지 않으면 TCP가 기본값으로 사용된다.
❗️주의할점 ❗️
- EXPOSE 명령문으로 지정된 포트는 해당 컨테이너의 내부에서만 유효하며, 호스트(host)컴퓨터에서는 이 포트를 바로 접근을 할 수 있는것은 아니다.
- 호스트 컴퓨터로부터 해당 포트로의 접근을 허용하려면, docker run 커맨드를 -p 옵션을 통해 호스트 컴퓨터의 특정 포트를 포워딩(forwarding) 해줘야 한다.
ARG
ARG <이름>
ARG <이름> =<기본값>
COPY
COPY <src>...<dest>
COPY ["<src>", ..., "<dest>"]
- 호스트 컴퓨터에 있는 디렉터리나 파일을 Docker 이미지의 파일 시스템으로 복사하기 위해서 사용된다. 절대 경로와 상대 경로를 모두 지원하며, 상대 경로를 사용할때는 이전에 등장하는 WORKDIR 명령문으로 작업 디렉토리를 어디로 전환을 해놨는지 고려해야 한다.
ENTRYPOINT
ENTRYPOINT ["<커맨드>", "<파라미터1>", "<파라미터2>"]
ENTRYPOINT <전체 커맨드>
- 이미지를 컨테이너로 띄울때 항상 실행되어야 하는 커맨드를 지정할때 사용한다. ENTRYPOINT 명령문은 Docker 이미지를 마치 하나의 실행 파일처럼 사용할때 유용하다. 왜냐하면 컨테이너가 뜰때 ENTRYPOINT 명령문으로 커맨드가 실행되고, 이 커맨드로 실행된 프로세스가 죽을때, 컨테이너도 따라서 종료되기 때문이다.