ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 도커 (8)컨테이너이름, rm, v, 요약, 리소스정리, cp, CMD & ENTRYPOINT
    docker 2022. 2. 26. 17:48

    ============

    container run할 때 이름 안주기

     

    C:\docker> docker container ls

    CONTAINER ID   IMAGE                 COMMAND                  CREATED          STATUS          PORTS                     NAMES

    2fdfc16ec42c   example/echo:latest   "/bin/bash"              23 seconds ago   Up 22 seconds   0.0.0.0:58496->8080/tcp   zealous_mcnulty ⇐ 해당 컨테이너가 detach 모드로 전환

    9317682730d9   example/echo:latest   "go run /echo/main.go"   5 minutes ago    Up 5 minutes    0.0.0.0:58470->8080/tcp   tender_merkle

                              docker container run --name 옵션을 생략하면 임의의 이름을 생성해서 제공

     

    웹서버가 하나밖에 없으면 쉽게 제어하려면 이름을 가져가는게 좋다. ID치려면 어려우니까

     

    근데 100개 띄우면 이름을 부여하는게 부담스러워진다

    ->운영환경에선 이름 사용 안해, 자동 부여되도록 해

     

    개발할 때나 컨테이너 한 두개 띄울 때 액세스 쉽게 하려고 이름 부여함

    포트랑 마찬가지네

     

    ============

    --rm

     

    컨테이너를 이름 부여해서 run하는건 좋지 않다

    운영할 땐 같은 컨테이너를 여러개 띄울텐데

    --name으로 이름 부여하고 같은 run을 두번 입력하면 --name이름 같다고 실행 안됨 유니크해야해

    stop해도 같은 이름으로 run안된다

    다시 띄우려면 rm해야해

     

    - 개발하는 단계에서 ID를 이용해서 access하려고 하면 헷갈림

    - 이름을 사용하려고 하면 중복되면 안되고

     

    개발 시 컨테이너가 종료되면 자동으로 삭제되게 설정할 수 있다, --rm옵션으로

    docker container run --name myreact-app --rm -itd -p 3000 myapp

    docker container stop myreact-app

    이제 stop하면 지워짐

     

    *저거 -P옵션하면 EXPOSE 3000이라고 돼 있으면 3000번 포트를 노출하고, 임의의 포트를 3000과 연결함

     EXPOSE 3000 + -P = -p 3000

     

    ---

    -v

    개발단계에서의 얘기

     

    PS C:\docker> docker container run --name myreact-app --rm -itd -p 8282:3000 myapp

    이 상태에서 리액트 어플리케이션의 내용을 변경하고 싶어

     : 내 PC의 소스 코드를 수정 → docker image build → docker container run

    이렇게 해야되는데 빌드하는데 시간이 오래 걸리고...

     

    내가 갖고 있는 파일을 실행 컨테이너와 공유할 수 있으면 어떨까?

     

    도커는 내가 준 파일을 특정디렉토리에 따놓고 그걸 run만 하고 있는데,

    배포말고 개발단계에서는 그 시간을 좀 줄이면 어떨까

    호스트의 특정 디렉토리를 컨테이너의 내부와 공유! 복사하고 빌드안해도 되게! 볼륨매핑!

     

    VOLUME을 이용해서 호스트의 특정 디렉터리를 컨테이너 내부와 공유해서 복사하고 빌드하는 시간을 단축 

    http://pyrasis.com/book/DockerForTheReallyImpatient/Chapter07/11

     

    컨테이너를 run하는데 -v옵션을 줘서 

    -v 호스트디렉토리 : 컨테이너내부디렉토리

     

    호스트 디렉토리를 컨테이너 내부 디렉토리와 연결

    내용을 바꾸면 변경자체가 공유돼있기 때문에 바뀐다, 컨테이너 run 중에도 바꿔도 요청 다시하면 바뀐다

     

    볼륨 : 호스트와 컨테이너가 공유디렉토리를 쓴다

     

    활용(1)

    호스트의 변경을 여러 컨테이너에 함께 반영하고 싶을 때

    웹서버를 여러개 띄웠는데, 소스코드가 전부 다르면 안되니까

    하나의 공유디렉토리를 걸어놓고 모든 컨테이너들이 소스코드를 받아가게

     

    활용(2)

    컨테이너가 휘발성 객체, 죽을수도 사라질수도

    일반적인 서비스용 컨테이너 스프링부트와같은, REST API를 제공하는 얘들은 돌다가 사라져도 또 띄우면 똑같은 동작을 할 수 있다 = stateless, 상태관리하지않고 동작하다 사라지면 또 띄우면 똑같이 동작

     

    그에 비해서 mysql서버는 계속 달라, 데이터가 쌓여, stateful한 서비스

    이건 컨테이너가 죽어버리면 거기있던 데이터가 날아가버리면 안된다

    stateful한 서비스들은 데이터 유지관리보관해야하는 기능이 필요하다, persistence하게 관리해야한다

    이때 볼륨매핑을 씀

    mysql이죽어서 다른 mysql이 올라오더라도 같은 상태로. 데이터를 컨테이너내부가 아니라 볼륨매핑을 통해 호스트측에다가

    여러개의 컨테이너에게 동일한 최신데이터를 줘야할 때!

     

    ============

    요약

     

    제일 중요한건 -itd 옵션

    입력과 출력을 공유하고

    detach모드로 동작시키고

     

    도커파일을 만들어서 내가만든 리액트, 자바를 이미지화

     

    실행중인 컨테이너에 attach할 때

    attach -> 빠져나오면 컨테이너가 죽어 그래서 detach키를 통해서 detach모드로 빠져나와야

    exec해서 쉘을 실행 -> 해당 컨테이너에 쉘이 제공돼야하는 경우 그렇게 빠져나오면 컨테이너의 메인프로세스는 동작하므로 컨테이너가 중지안됨

     

    --rm 하면 개발환경에서 유용

    포트바인딩은 -p

    컨테이너 port는 고정돼도 상관없다 컨테이너마다 전부 8080이어도 괜찮

    호스트port는 걔마다 달라야해, 운영단계에선 일일이 지정해주는것보단 지정하지 않고 자유롭게 배정될 수 있도록 하는게 방법

     

    이미지만들때 사용자 입력 안들어가게 : -y말하는거겠지

    파일사이즈줄이기 : &&말하는거겠지

     

    ============

    0)

    컨테이너도 하나의 컴퓨터니까 포트도 여러개고

    거기에 서버프로그램 여러개 두면, 각각 포트가 필요할텐데(컨테이너 안에 db, 스프링부트, 리액트 각각 설정에 포트를 써놨을 텐데)

    EXPOSE를 보다가, 왜 Dockerfile에서 왜 딱히 저 여러개랑 각각 다른 호스트 포트랑 연결하는 설정이 없는것 같냐

    이미지 만들때도 -p옵션에서 하나만 연결하고

    ->컨테이너에 서버를 여러개 둘 수 있다o, 얘네 각각 바깥 포트 몇번이랑 연결할지 설정할 수 있다o

     = 컨테이너 하나에 DB, 리액트, 스프링부트 둘 수 있고 명령어나 Dockerfile로 각각 다른 호스트 포트와 연결할 수 있다

    ->근데! 좋은 설계는 컨테이너 당 프로그램 하나 돌리는게 깔끔한거고 원칙이래!이게 바로 시원한 답변이었다

    ->좋은 설계는 DB, 리액트, 스프링부트를 각각 컨테이너 하나씩에만 둔다 서로 연결을 할 수 있는 방법이 있다(당연), 쉽게하는 건 도커컴포즈지

     

    ============

    리소스 정리 (모든 컨테이너와 이미지를 삭제)

    PS C:\Users\myanj> docker container rm -f $(docker container ls -aq)

    PS C:\Users\myanj> docker image rm -f $(docker image ls -aq)

     

    ============ 

    cp(▽볼륨매핑하면 될걸 왜..)

    nginx (웹 서버) 이미지를 이용해서 컨테이너를 생성 

    PS C:\Users\myanj> mkdir c:\docker\webroot

    PS C:\Users\myanj> docker run -itd --name mywebserver -p 8080:80 nginx

     

    이제 컨테이너 내부의 파일을 수정해보려고해

     

    attach해서 들어가봤더니 리스닝중이야

    detach모드 : 컨+p+q로 해서

    exec로 다시 해보자

     

    (1)

    PS C:\Users\myanj> docker container attach mywebserver

    2022/01/26 00:38:40 [notice] 39#39: signal 28 (SIGWINCH) received

    2022/01/26 00:38:40 [notice] 38#38: signal 28 (SIGWINCH) received

    :

    Ctrl + p + q ⇒ detach 모드로 전환

     

    (2)

    PS C:\Users\myanj> docker container exec -it mywebserver /bin/bash

    root@bca3ef603d99:/#

     

    root@bca3ef603d99:/# cd /usr/share/nginx/html/ ⇐ nginx의 기본 웹 루트 디렉터리

    root@bca3ef603d99:/usr/share/nginx/html# ls

    50x.html  index.html

    root@bca3ef603d99:/usr/share/nginx/html# cat index.html ⇐ 브라우저를 통해서 확인한 페이지

    <!DOCTYPE html>

    <html>

    <head>

     :

     :

     

    근데 vi해보니까 없어서 exit로 빠져나옴(다운받아서 해도 되지만 그냥 나옴)

     

    (3)

    컨테이너의 파일을 가져와서, 수정하고, 다시 넣으려고 해

    cp :

    ▽앞에것을 복사, 뒤의 것이 복사할 곳.  : 로 컨테이너인지 호스트인지를 구분

     

    docker container cp mywebserver:/usr/share/nginx/html .

    앞에 있는걸 . 로 가져와

    한칸 띄우기 전까지 SRC, 뒤에것이 목적지

     

    ============

    수정을 한 뒤 수정한 index.html 파일을 컨테이너 내부로 복사

    PS C:\docker\webroot> docker container cp .\html\index.html mywebserver:/usr/share/nginx/html\index.html

     

    확인할땐 웹서버로 요청을 해보든지

    cat으로 하든지

    PS C:\docker\webroot> docker container exec mywebserver cat /usr/share/nginx/html/index.html

     

    ============

    commit

     

    이때 ! 변경된 내용을 포함하고 있는 컨테이너를 이미지로 저장, 

    -a : 저작자

    -m : 커밋메시지

     

    컨테이너 이름 다음에 이름을 주기
    PS C:\docker\webroot> docker commit -a "만든사람 myanjini" -m "새로운 컨텐츠를 포함한 웹 서버" mywebserver mynewwebserver

    sha256:4ce4c3809f8968157c11fcd46f124d0b51e34ec43cb52a5884d363aa55c51721

     

    PS C:\docker\webroot> docker image ls

    REPOSITORY       TAG       IMAGE ID       CREATED          SIZE

    mynewwebserver   latest    4ce4c3809f89   21 seconds ago   141MB

    nginx            latest    605c77e624dd   3 weeks ago      141MB

     

    ============

    생성한거 도커허브에 등록하기

    1.태그바꾸기

    docker image tag 

    내 계정명이 포함돼있는 새로운 이름으로 해야해

    docker image tag mynewwebserver:latest myanjini/mynewwebserver:1.0

    (처음에 commit할 때 이름줘도 된다)

     

    2.

    docker push 이미지명

    PS C:\docker\webroot> docker push myanjini/mynewwebserver:1.0

     

     

    ============

    도커 허브에 등록된 이미지를 이용(▽원래있는걸로하잖아)해서 새로운 컨텐츠를 포함한 컨테이너를 실행

    docker container run --name mynewwebserver -d -p 9090:80 이미지이름

    PS C:\docker\webroot> docker container run --name mynewwebserver -d -p 9090:80 myanjini/mynewwebserver:1.0

     

    ============

    CMD vs ENTRYPOINT

    도커파일에서 두개 다 컨테이너가 실행됐을 때 명령어를 실행해주는 기능

     

    이재홍 아저씨 문서에 다 있다

    http://www.pyrasis.com/book/DockerForTheReallyImpatient/Chapter07/06

     

    ============

    CMD

    FROM ubuntu

    CMD  ["echo", "Hello"]

     

    PS C:\docker> docker image build -t cmd_img -f Dockerfile_cmd .

    PS C:\docker> docker container run cmd_img

    Hello

     

    근데?

    PS C:\docker> docker container run --help

    Usage:  docker container run [OPTIONS] IMAGE [COMMAND] [ARG...]

    Run a command in a new container

    :

     

    PS C:\docker> docker container run cmd_img echo World

    World

     

    World만 나와

     

    ⇐ Dockerfile의 CMD 내용을 container run 명령에서 전달된 명령어로 덮어써서 실행

     

    ============

    ENTRYPOINT

    FROM ubuntu

    ENTRYPOINT  ["echo", "Hello"]

    PS C:\docker> docker image build -t entrypoint_img -f Dockerfile_entrypoint .

    PS C:\docker> docker container run entrypoint_img

    Hello

     

    PS C:\docker> docker container run entrypoint_img echo World

    Hello echo World

     

    뒤의 명령어가 인자값으로 사용이 된다

    ▽그냥 echo Hello echo World가 이어 쓰이나봐?

     

    이렇게 두개가 동작하는 방식이 다르다

    ENTRYPOINT는 전달하는게 파라미터값으로 반영 : 컨테이너가 실행될 때 그 명령어가 쓰여야된다고 만드는애가 지정하는 것 

    CMD는 덮어쓰임 : 경우에 따라 실행되는 명령어가 바뀌어도 되는 경우

Designed by Tistory.