Docker? - 2 (이미지 생성 및 RUN)

박정훈·2023년 4월 23일
0

Docker

목록 보기
5/6
post-thumbnail

이미지

공식적인 이미지를 지원 해 주는 곳이 있다. docker hub가 그곳이다.
이미지는 컨테이너의 블루프린터라고 했다. 이 친구를 통해 컨테이너라는 인스턴스를 만들어보자.

cmd 창을 열고docker run node를 치면

현재 폴더위치에서 이미지를 찾아 컨테이너를 생성하는 것인데, 난 지금 받아놓은게 없다. 따라서 docker hub에서 지원하는 공식 이미지를 열심히 다운받는 것을 확인할 수 있었다.

docker ps -a
ps 는 프로세스를 의미하며 -a는 all을 의미힌다.

ID, IMAGE, COMMAND... 등등을 확인할 수 있다. 상태를 보면 Exited라고 되어있다. 나는 실행한거 같은데...

노드 이미지를 기반으로 하는 컨테이너를 실행하긴 했지만 이것만으로는 큰 의미가 없다.

docker run -it node

도커에게 컨테이너 내부에서 호스팅 머신으로 인테럭티브 세션을 노출시키라는 명령어다.
노드가 생성된 컨테이너 내부에서 실행되고 있으며, -it 플래그를 추가함으로써 터미널로 들어가 해당 컨테이너 및 컨테이너에서 실행중인 노드와 상호작용할 수 있다.

나의 로컬에 설치되어있는 node 버전과 컨테이너의 이미지로 가져온 node 버전이 다르다는것 또한 확인할 수 있다.

Dockerfile

vscode에서 Dockerfile을 통해 이미지를 빌드할수 있다. vscode에서 파일을 만들듯이 Dcokerfile이란 이름으로 파일을 만들어주자. 여기에는 각종 명령어가 들어가게 된다. 하나씩 살펴보자.
일단 서버 하나 만들고!

const express = require("express");

const app = express();

app.use("/", (req, res) => {
  res.send("안녕! 바부야!");
});

app.listen(80, () => {
  console.log("80 포트에서 서버가 실행중입니다.");
});

FROM

FROM node

FROM은 어떤 리눅스를 사용할 것인지에 대한 것이다.
즉, 어떤 베이스 이미지를 사용할 것인가?
python인지, node인지, java인지 등에 따라 여러 OS버전이 있다.
우리의 로컬에 존재하거나 도커허브에 존재하는 이미지도 가능하다.

COPY

COPY는 말 그대로 파일을 복사한다.

COPY . /app

첫번째 . 은 도커파일이 포함된 현재 위치에 있는 모든 폴더, 하위 폴더 및 파일을 몽땅 복사하는 것이다.
두번째 /app 은 그 파일들을 저장해야 하는 이미지 내부의 경로이다.
현재 디렉토리의 소스코드를 app디렉토리에 copy하라는 뜻이다.

RUN

이미지에서 명령을 실행시키고 싶을때 사용한다.

RUN npm install

근데 명령을 특정 위치에서 실행시키고 싶다?

WORKDIR

WORKDIR /app

현재 작업 디렉토리를 의미한다.
npm install을 app 폴더 내에서 실행하도록 한다. WORKDIR 이후의 모든 후속 명령이 해당 폴더 내부에서 실행되도록 한다.
즉 후속 명령들은 WORKDIR의 경로를 기준으로 실행된다. 다음과 같이 사용할수 있겠다.

FROM node

WORKDIR /app

COPY . /app
// 또는 COPY . ./  -> WORKDIR기준이기 때문이다.

RUN npm install

모든 명령어 입력이 끝나고 이미지를 빌드하고자 한다.

CMD

RUN과 CMD 둘 다 실행하라는 명령어다. 차이점이 있다면, RUN은 이미지가 생성될 때 실행되고, CMD는 이미지를 기반으로 컨테이너가 시작될 때 실행된다는 것이다. 또한 CMD의 경우 사용법이 조금 다르다.

FROM node

WORKDIR /app

COPY . /app
// 또는 COPY . ./  -> WORKDIR기준이기 때문이다.

RUN npm install

CMD ['node', 'server.js']

도커 컨테이너는 격리되어 있다. 즉, 자체 내부 네트워크를 가지고 있다. 컨테이너 내부의 노드 앱에서 특정 포트를 수신할 때 컨테이너는 그 포트를 우리의 로컬에 노출시키지 않는다. 위의 코드에서 서버가 80번을 listen하고 있으므로, 도커에서 그 포트를 개방시켜보자.

FROM node

WORKDIR /app

COPY . /app
// 또는 COPY . ./  -> WORKDIR기준이기 때문이다.

RUN npm install

EXPOSE 80

CMD ['node', 'server.js']

이미지 생성

이렇게 작성한 Dockerfile로 커스텀 이미지를 만들어 보자.

docker build .

Dockerfile을 build 시킬껀데 그 경로는 . 즉, 현재 명령어를 입력하고 있는 그 장소란 뜻이된다.
명령어를 입력하면 우리가 작성한 명령어에 따라 작업이 쭉쭉 진행되고 ID가 생성된다.
sha256 뒤로 엄청나게 길게 있는게 ID다. 해당 ID로 docker를 run 시키자.

docker run ID

이제 종료되지 않고 컨테이너는 실행을 유지하게 된다. 그치만 localhost를 뛰워보면 실행되고 있지 않는 것을 볼수 있다.
도커가 제대로 실행되고 있는지 확인해보자.

docker ps // 현재 실행중인 프로세스만을 보여준다.

방금 run 시킨 이미지가 보인다. 이 친구의 동작을 멈추려면 NAMES로 stop시키면된다.

docker stop recursing_ellis

물론 docker ps -a 하면 동작을 멈춘 애들까지 모두 리스트 확인 가능하다.

그래서 왜 localhost에 안떴는데...

명령어로 작성한 EXPOSE 80 같은 경우 그저 분명히 명시하기 위한 작성이다. 없어도 동작하며 실제로 도커에게 이를 알리려면 특정 플래그를 도커를 run할때 추가해야 한다. 이 부분만이 실제로 필요한 부분이다.

docker run -p 3000:80 image ID

p는 publish를 의미하는데 이를 통해 도커에게 우리의 로컬 머신의 어떤 포트가 도커의 특정 포트에 액세스 할 수 있는지 알려줄수 있다. 위의 경우는 로컬은 3000이며, 도커 내부 포트는 80이다. 드디어 앱이 제대로 실행되는것을 확인할 수 있다.

profile
그냥 개인적으로 공부한 글들에 불과

0개의 댓글