ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Docker Custom Image
    Infra/컨테이너 2022. 8. 20. 18:59
    FROM node
    
    WORKDIR /app
    
    COPY . /app
    
    RUN npm install
    
    EXPOSE 8080
    
    CMD node server.js

    위 Dockerfile을 Image로 변환한 다음 궁극적으로는 Container로 변환하는 방법은 무엇일까?

     

    build

    docker run X

    docker build O

    VScode 내장 터미널을 열어 이번에는 docker run이 아닌 docker build를 입력해준다. 왜냐하면 지금 단계에서는 image를 실행하고 싶지 않기 때문이다.

     

    지금은 무엇보다도 먼저 Image를 만들어야 하는 단계이다. 즉 Dockerfile에 적힌 명령에 따라 Image를 만들고자 하는 것인데 build명령어로 그것을 수행할 수 있다.

     

    docker build .

    Dockerfile을 기반으로 새 커스텀 이미지를 build하도록 Docker에게 지시한다. 그리고 build뒤에 Dockerfile을 찾을 수 있는 경로를 알려주어야 한다. 

     

    위 터미널 명령 같이 '.'을 입력하여, Docker에게 이 명령을 실행하는 곳 과  동일한 경로 선상에 폴더에 Dockerfile이 존재함을 알린다.

     

    terminal에 docker build . 명령어를 입력하면 위와 같이 Image가 생성된다. 위 그림을 통해 몇 가지 단계가 실행되는 것을 확인 할 수있다.

     

    custom Image를 build하고 나서 출력된 Image의 id로 Container를 실행

    생성된 ID를 복사한 다음 docker run 명령어 뒤에 그 아이디를 넣고 터미널에서 실행한다. 그러면 해당 ID의 Container가 실행되고 완료되지 않고 계속 실행되는 상태가 지속되는 것을 확인 할 수 있다.

     

    그 이유는 CMD에서 실행한 명령이 노드 서버를 시작하기 때문이다. 따라서 노드 서버는 완료되지 않고 진행 중인 프로세스가 된다. 그래서 Container 또한 실행을 계속 유지한다.

     

    Container가 시작될 때 실행된 명령이 완료되지 않았기 때문이다. 그렇게 Container는 계속 실행된다. 하지만 브라우저를 통해 localhost:8080을 방문해도 웹사이트가 표시되지 않는 것을 확인할 수있다. Dockerfile에서 포트를 노출했음에도 불구하고 접속할 수 없는것이다.

     

    그렇다면 왜 작동하지 않는 것일까?

     

    동작 중인 Container 확인

    이때  VScode에서 새 터미널을 연뒤에 docker ps 명령어를 입력한다. docker ps는 뒤에 -a option을 붙이지 않으면 현재 실행중인 프로세스만 표시된다.

     

    위 그림에서 확인할 수 있듯이 직접 custom한 image를 기반으로하는 Container가 하나있다. STATUS를 확인하면 여전히 실행 되고 있는 것을 확인할 수 있다.  왜냐하면 앞서 언급하바와 같이 Container의 프로세스가 종료되지 않았기 때문이다.

     

    Container 수동 정지

    터미널에 docker stop 뒤에 Docker에서 임의로 지어준 Container에 이름을 넣어 해당 Container를 수동으로 종료시킨다. 

     

    Container를 수동으로 정지 시킨뒤에 docker ps 명령어로 실행중인 Container를 확인하면 실행중인 Container를 더 이상 볼 수 없다. 대신에 이제 -a 옵션을 붙여서 Container를 확인해야 한다.

     

    명령어를 치고 Container 현황을 살펴보면 방금전 실행되었던 Container의 상태는 Exited로 종료되었음을 확인할 수 있다.

     

    근데 무엇이 잘못되었던 걸까? 왜 custom image로 build된 Container에서 실행되 노드 서버는 localhost의 포트 8080에서 수신 대기(request 대기 즉 매핑된 URL에대한 request대기)를 하지 않았던 것일까? 한가지 단계가 빠져있기 때문이다.

     

    Dockerfile에 EXPOSE 8080명령이 있었지만 실제로 이 명령은 documentation 목적으로만 추가되었을 뿐이라는 것이다. 즉 아무 것도 하지 않는다.

     

    Loacal port와 Container port 매칭하기 

    documentation을 추가하는 것은 모범적인 사례이고 분명히 해당 명령을 추가하여 Container의 포트를 노출해야 하지만  그외에 추가적으로 해야 할 것이 있다. 이 EXPOSE 8080명령을 제거할 수도 있지만 여전히 정상 작동 시킬 수있다. EXPOSE 명령은 분명히 선택적 사항이지만 되도록이면 추가하는 것을 권장한다.

     

    docker run -p 7000:8080 f3e9418ecd233eb3c3ddaf5587da819587fa8771b0d377867e75e4caff46c940

    정말 중요한 것은 컨테이너를 docker run으로 실행할 때 특별한 옵션이 추가 되어야 한다는 것이다. Container를 실행할 때 run과 Container를 지칭하는 이름이나 ID사이에 플래그를 추가하는 것이다. -p 플래그를 넣는 것인데 이는 publish의 약자이다.

     

    위와 같은 플래그를 넣음으로 인해 Docker에게 어떤 local 포트가 있는지 알려줄 수 있다. local 컴퓨터의 어떤 포트를 통해서 실행 시킬지와 어떤 포트를 통해서 Container 내부에 접근할 수 있는지를 정하는 것이다. 그러므로 -p 다음에 Container Aplication에 접근하려는 local 환경의 포트를 지정한다. 예시에서는 포트 7000을 사용하였다.

     

    local port번호 다음에 ':'을 넣고 Container 내부에서 노출할 포트 번호를 넣는다. 여기에 Dockerfile을 작성할 때 설정했던  

    EXPOSE와 같은 번호를 넣어야 함으로 예시에서는 8080포트가 된다.

    위 그림대로 명령어를 실행한후에 브라우저에 가서 localhost:7000에 접속하면 Container안에 들어 있는 Application인 노드 서버가 정상적으로 수신대기를 해 매칭된 URL에 대해 올바른 Response를 보내고 있는 것을 확인할 수 있다.

     

    정리

    이것이 custom image로 Container를 띄우는 방식이다. Dockerfile을 이용해 custom image를 만들 수 있는데  base image(node)를 기반으로 하여 Container 안의 설치된 node를 실행시킬 수 있는 자체 명령어(RUN)와 자체 노드 앱(server.js)를 포함하고 있다.

     

    NodeJS를 base image로 하는 custom image가 있고, 이는 Dockerfile을 통해서 만들수 있는데 Dockerfile에는 몇가지 명령이 있고 이 명령을 통해 코드를 복사(COPY)하고 종속성을 설치한다.(RUN)

     

    그런 후에 그 Dockerfile을 이용해서 docker build라는 명령어로 custom image를 만들고, docker run 이라는 명령어로 custom image를 기반으로 Container를 실행한다.

     

    custom image로 실행한 Container는 여전히 실행 중이다. 이것을 멈추고 싶으면 docker ps로 실행 중인 Container의 이름을 찾고, 터미널에서 docker stop(컨테이너 이름) 명령을 하므로써 실행을 종료시킬 수 있다.

     

     

    댓글

Designed by Tistory.