Home Docker 4 - Container Option
Post
Cancel

Docker 4 - Container Option

Container Option

  • container의 실행부터 종료까지
    명령어만 본다면 간단히 끝났다.
  • create - start 와 run을 보면
    선택적으로 option을 넣을 수 있었다.
  • 이 때 들어가는 option이 좀 많은데
    이미 image에 명시된 조건을
    조정할 때 쓰이는것같다.
  • create - start와 run은
    결국엔 같은 기능이므로
    대부분의 option을 공유한다.
  • 자주 쓰는거 위주로 필요할때마다 추가.

--name

  • container name 지정

    1
    
    docker create --name tc2 tomcat:latest
    
    1
    2
    
    CONTAINER ID  IMAGE   COMMAND            CREATED     STATUS                      PORTS  NAMES
    b2f22b9f2fc2  tomcat  "catalina.sh run"  3 days ago  Exited (143) 40 hours ago          tc2
    
  • option 없이 생성하면

    1
    2
    
    CONTAINER ID   IMAGE  COMMAND      CREATED          STATUS   PORTS  NAMES
    5ad53c428d37   centos "/bin/bash"  57 seconds ago   Created         peaceful_kare
    

    이름이 아무렇게나 만들어지는데
    이걸 지정할 수 있음.

  • container에 대한 조작은
    id나 name으로 하기때문에
    보통 이게 기본적으로 쓰임.


-p , --publish

  • network 사용이 필요할 때
    외부로 공개할 포트를 지정
  • container가 독립공간이므로
    쓰는 port가 있더라도
    net으로 외부에서 접속할 수 없고
    이 port를 host에 연결해야한다.
  • 포트 포워딩 할때 쓰는것같은데
    포트 써야할 떄 이거 안써주면 안되는듯?
  • 인자값은 <공개 port>:<image port>.
  • container에서 쓰일 port정보는
    image에 써있다. 예를들어 tomcat은

    1
    2
    3
    
    "ExposedPorts": {
                    "8080/tcp": {}
                    },
    
  • publish없이 실행은 할 수 있다.

    1
    
    docker --name tc tomcat
    
    • 이 경우 NetworkSettings에
      별다른 정보가 없다.
    • 이 상태로 실행해도
      할수있는게 없다.
    • network를 통해 접속할 수 없다.
      가 원래 결론이었고 별도로
      아마 container에서 갖고있는
      bash에는 될것같음.
  • 반대로

    1
    
    docker --name tc2 -p 9999:8080 tomcat
    

    이 경우 실행해보면

    1
    
    docker ps
    
    1
    2
    
    CONTAINER ID   IMAGE           COMMAND             CREATED          STATUS          PORTS                    NAMES
    cd214ecd1a84   tomcat:latest   "catalina.sh run"   19 minutes ago   Up 19 minutes   0.0.0.0:9999->8080/tcp   tc2
    
    • option없이 했을때랑 다르게
      PORTS에 조건이 더 생겼다.
    • 또한NetworkSettings에
      관련 정보들이 들어가 있는데
      둘 간의 차이를 보면

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      
      <tc>
          
      "NetworkSettings": {
        ...
        "Ports": {},
        "SandboxKey": "/var/run/docker/netns/e04b1ad8ff29",
        "SecondaryIPAddresses": null,
        "SecondaryIPv6Addresses": null,
        "EndpointID": "",
        "Gateway": "",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "IPAddress": "",
        "IPPrefixLen": 0,
        "IPv6Gateway": "",
        "MacAddress": "",
        "Networks": {
          "bridge": {
            "IPAMConfig": null,
            "Links": null,
            "Aliases": null,
            "NetworkID": "9b025930652cabdf1c38676ce480a6df5b82598f2996429ebf7067db9e0a976f",
            "EndpointID": "",
            "Gateway": "",
            "IPAddress": "",
            "IPPrefixLen": 0,
            "IPv6Gateway": "",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "MacAddress": "",
            "DriverOpts": null
          }
        }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      
      <tc2>
          
      "NetworkSettings": {
        ...
        "Ports": {
            "8080/tcp": [
                {
                    "HostIp": "0.0.0.0",
                    "HostPort": "9999"
                }
            ]
        },
        "SandboxKey": "/var/run/docker/netns/c6013703193c",
        "SecondaryIPAddresses": null,
        "SecondaryIPv6Addresses": null,
        "EndpointID": "0167447f944aa96aa3b4843afef94fe5b2c8ca4f1a7757fad4a222dffa17a261",
        "Gateway": "172.17.0.1",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "IPAddress": "172.17.0.2",
        "IPPrefixLen": 16,
        "IPv6Gateway": "",
        "MacAddress": "02:42:ac:11:00:02",
        "Networks": {
          "bridge": {
            "IPAMConfig": null,
            "Links": null,
            "Aliases": null,
            "NetworkID": "9b025930652cabdf1c38676ce480a6df5b82598f2996429ebf7067db9e0a976f",
            "EndpointID": "0167447f944aa96aa3b4843afef94fe5b2c8ca4f1a7757fad4a222dffa17a261",
            "Gateway": "172.17.0.1",
            "IPAddress": "172.17.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "MacAddress": "02:42:ac:11:00:02",
            "DriverOpts": null
          }
        }
      
  • host를 확인해 보면
    • windows

      1
      2
      3
      4
      5
      
          
      netstat -an | findstr :9999
        TCP    0.0.0.0:9999   0.0.0.0:0  LISTENING
        TCP    [::]:9999      [::]:0     LISTENING
        TCP    [::1]:9999     [::]:0     LISTENING
      
    • wsl

      1
      2
      3
      
          
      netstat -an | grep :9999
      tcp6       0      0 :::9999                 :::*                    LISTEN
      
    • 둘 다 option으로 줬던
      port를 쓰기 시작하고 이 때부터
      network 관련 기능을 쓸 수 있어진다.


-t, --tty

  • tty 모드를 사용한다.
  • bash를 사용하려면 써야한다.
  • 먼저 centos를 option없이 해보면

    1
    
    docker run --name test centos:latest
    
    1
    2
    3
    
    docker ps
      
    CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
    
    1
    2
    3
    4
    
    docker ps -a   
      
    CONTAINER ID   IMAGE                       COMMAND                  CREATED             STATUS                           PORTS     NAMES
    d7de0fda2455   centos:latest               "/bin/bash"              7 seconds ago       Exited (0) 7 seconds ago                   test
    

    실행했던 흔적은 남아있는데
    아무 반응없이 꺼진다.
    Exited로 앞서 설명처럼
    명령어 실행 후 끝난것.

  • docker 문서에서도 tty는
    pseudo-TTY를 할당한다고 설명하는데
    tty는 terminal, bash, shell 등이 관련있고
    이걸 정리할 수 있다면 따로.
  • 아무튼 대충 이해한바로는
    명령 하나만 보내는게 이 전까지 방법이면
    terminal을 사용하는 환경으로 바꿔주는듯함.
  • 다시말해 명령전달에서 terminal실행으로.
  • 이 명령어를 써야 bash를 사용한다.

    1
    2
    
    docker run -t --name test centos:latest
    [root@59279bc00159 /]#
    
  • 다만, 위 상태에서 뭘 더 할수있는건 없음
    그 이유와 필요한건 다음으로.

-i, --interective

  • -t의 경우 bash를 실행하고
    결과만 보여주고 명령을 전달할수 없었는데
    container는 기본적으로
    stdout으로 동작한다.
    그래서 더이상 할수있는게 없던것.
  • -i 는 stdin을 추가해준다.

    1
    2
    3
    4
    5
    
    docker run --name test -i -t centos:latest
      
    [root@8e7aedf13e36 /]#
    [root@8e7aedf13e36 /]# ls
    bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
    
    1
    2
    
    docker create --name test -i -t centos
    docker start test
    
    • run의 경우 입력도 가능해짐.
    • create-start의 경우
      exec, attach등으로
      container로 접속을 하면 됨.
      이건 나중에.

-d --detach

  • run의 경우 -t -i 를 쓰면
    시작되면서 container의 bash로
    바로 연결되는데 이걸 방지함.
  • daemon, background 그런거.
    1
    
    docker run --name test -i -t -d centos:latest
    

--rm

  • 위와같이 테스트 등에 쓸 container는
    유지할필요가 없다.

    1
    
    docker run --rm -t -i centos:latest
    
  • container가 종료되면 자동으로 삭제한다.


-e, --env

  • 환경변수를 설정한다.
  • 일단은 db쓸때 사용해봐서
    db를 예로 들기로 한다.
  • 근데 다른 용도의 사용도 많은듯함.
  • mysql을 기준으로

    1
    2
    3
    
    docker create --name test -p 3306:3306 \
    -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=Sample_db \
    -e MYSQL_USER=user -e MYSQL_PASSWORD=passwd mysql:latest
    
  • option에 -e는 여러개일 수 있음.
    • MYSQL_ROOT_PASSWORD : root계정 pw
    • MYSQL_DATABASE : db 생성.
    • MYSQL_USER : user 계정
    • MYSQL_PASSWORD : user 계정 pw
    • 이건 여기는 안썼는데
      MYSQL_ALLOW_EMPTY_PASSWORD :
      yes/no로 root pw 강제 설정 유무
  • 환경설정 적용확인은 db접속으로.
    • datagrip
      ip, port로 접속하는데
      아무튼 됨 근데 사진찍기 귀찮음.
    • console

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      
      docker exec -i -t test bash
          
      bash-4.4# mysql -u root -p
      Enter password: 
      Welcome to the MySQL monitor.  Commands end with ; or \g.
      Your MySQL connection id is 15
      Server version: 8.0.29 MySQL Community Server - GPL
          
      Copyright (c) 2000, 2022, Oracle and/or its affiliates.
          
      Oracle is a registered trademark of Oracle Corporation and/or its
      affiliates. Other names may be trademarks of their respective
      owners.
          
      Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
          
      mysql> show databases;
      +--------------------+
      | Database           |
      +--------------------+
      | Sample_db          |
      | information_schema |
      | mysql              |
      | performance_schema |
      | sys                |
      +--------------------+
      5 rows in set (0.00 sec)
          
      mysql> exit
      Bye
      bash-4.4# mysql -u user -p
      Enter password: 
      Welcome to the MySQL monitor.  Commands end with ; or \g.
      Your MySQL connection id is 16
      Server version: 8.0.29 MySQL Community Server - GPL
          
      Copyright (c) 2000, 2022, Oracle and/or its affiliates.
          
      Oracle is a registered trademark of Oracle Corporation and/or its
      affiliates. Other names may be trademarks of their respective
      owners.
          
      Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
          
      mysql> show databases;
      +--------------------+
      | Database           |
      +--------------------+
      | Sample_db          |
      | information_schema |
      +--------------------+
      2 rows in set (0.01 sec)
          
      mysql>
      
      • option으로 줬던 계정과
        sample_db가 있다.
  • inspection을 비교해보면
    이와 관련해 달라지는 구간이 있는데
    Config-Env가 그렇다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
      <mysql image>
        
      "Env": [
          "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
          "GOSU_VERSION=1.14",
          "MYSQL_MAJOR=8.0",
          "MYSQL_VERSION=8.0.29-1.el8",
          "MYSQL_SHELL_VERSION=8.0.29-1.el8"
      ],
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
      <test container>
        
      "Env": [
          "MYSQL_ROOT_PASSWORD=root",
          "MYSQL_DATABASE=Sample_db",
          "MYSQL_USER=user",
          "MYSQL_PASSWORD=passwd",
          "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
          "GOSU_VERSION=1.14",
          "MYSQL_MAJOR=8.0",
          "MYSQL_VERSION=8.0.29-1.el8",
          "MYSQL_SHELL_VERSION=8.0.29-1.el8"
      ],
    
  • 일단은 db를 예시로 들었지만
    이 옵션은 활용도에 따라
    사용할수 있는 범위가 넓어지고
    image에 따라 쓸 수 있는 env가 다르다.

-v, --volume

  • container의 data가 저장될
    위치를 지정한다.
  • container는 상태가 저장되지 않는다.
    container가 삭제되면
    내부에서 쓰던 data도 삭제된다.
  • container의 data는 필요하다면
    기본적으로 volume으로 관리되는데
    보통 container랑 생사를 같이함.
  • 이 volume을 조정해 data를
    container 외부에 저장하면서
    container에 상관없이
    data를 영속적으로 보존할 수 있다.
  • 부가적으로 container끼리
    data를 공유하는 효과도 있다.
  • volume 관련 설정은 Mounts에 있다.

    1
    2
    3
    
    docker create --name test -p 3306:3306 \
    -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=Sample_db \
    -e MYSQL_USER=user -e MYSQL_PASSWORD=passwd mysql:latest
    
    1
    
    docker inspect test
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    "Mounts": [
      {
        "Type": "volume",
        "Name": "7bf5fb839a6c7e953b3113b94bc8fc3977ffb94ce3c9d18df57331629798a252",
        "Source": "/var/lib/docker/volumes/7bf5fb839a6c7e953b3113b94bc8fc3977ffb94ce3c9d18df57331629798a252/_data",
        "Destination": "/var/lib/mysql",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
      }
    ],
    
    • 아무런 설정없이 만든경우
      volume은 임의로 만들어져 할당된다.
    • volume은 필요한 경우 생성된다.
      위는 db라서 생성됐지만
      os나 언어 container의 경우
      이부분이 비어있음.
    • 실제로 volume는 Source에 있다고 하는데
      linux같은 경우가 그렇고
      wsl은 \\\wsl$\docker-desktop-data\
      version-pack-data\community\
      docker\volumes\<volume name>\\_data
      에 있다.
    • Destination은 container내부에
      data가 쌓이는 위치
  • 같은 기능의 option으로
    --mount가 있는데 --mount를 더 권장함.
    더 명시적이고 더 많이 쓸 수 있어서.
  • docker document에서는
    크게 3가지 방법을 소개한다.

Volume

  • docker에서 생성, 관리하는 data.
  • 이 방법을 더 권장하고 있다.
  • os에 따라 dir등이 달라질 수 있는데
    이건 docker에서 관리하기때문에
    신경쓸필요가 적어짐.
  • 등등 그 외에 많은 이점을 설명하고 있음.
  • 아마 기본으로 설정된방법인것같은데
    위처럼 아무 조건없이 만들어졌을 떄
    type을 보면 volume이다.
  • volume은

    1
    
    docker volume ls
    

    ls로 확인할 수 있는데
    보통은 이름이 무작위로 만들어져있고
    volume에 대한 확인또한

    1
    
    docker volume inspect <volume name>
    

    inspect로 가능하다.

  • container에 특정 volume을
    명시하기 위해서는
    먼저 volume을 생성해야한다.

    1
    
    docker volume create [OPTIONS] [VOLUME]
    

    예를들어

    1
    
    docker volume create test_vol
    
  • volume를 container에 연결한다.

    1
    2
    3
    4
    
    docker create -v test_vol:/var/lib/mysql \
    --name test -p 3306:3306 \
    -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=Sample_db \
    -e MYSQL_USER=user -e MYSQL_PASSWORD=passwd mysql:latest
    
    • -v 부분이고
      <volume name> : <target>
    • target는 container내부의 경로로
      dir이나 file상관없고
      dir경우 없으면 생성까지 해줌
    • mysql은 Destination이 명시되어있었고
      그 위치를 생성한 volume으로 mount한것.
      Destination이 없더라도 혹은 필요에 따라
      특정 dir을 쓰면 됨.
  • container의 해당 부분을 확인해보면

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    "Mounts": [
      {
        "Type": "volume",
        "Name": "test_vol",
        "Source": "/var/lib/docker/volumes/test_vol/_data",
        "Destination": "/var/lib/mysql",
        "Driver": "local",
        "Mode": "z",
        "RW": true,
        "Propagation": ""
      }
    ],
    

    실행하면 -e때랑 같다.

  • 이 상태에서 container를 삭제하고
    -e MYSQL_DATABASE=Sample_db를
    지운상태로 다시 생성한다.
  • 이 container에는
    Sample_db가 없어야 하지만
    이 전 data는 volume에 여전히 있으므로
    show databases; 하면 보임.
  • 따라서 이 volume만 지워지지 않는다면
    container에 상관없이
    data를 보호할 수 있음.

Bind mounts

  • host의 임의의 경로에
    container를 mount한다.
  • volume도 경로를 따라가면
    host에서 찾을 수 있었는데
    docker에서 관리하는 data형식이었다면
    이 경우는 host의 dir을 직접적으로 사용.
  • option에서 volume 자리에
    host의 dir을 쓰면 된다.

    1
    2
    
    docker create --name test1 -i -t -v ~/test:/test centos:latest
    docker create --name test2 -i -t -v ~/test:/test centos:latest
    

    결과는 volume mount랑 같음.

  • inspect경우 type이 달라진다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    "Mounts": [
      {
        "Type": "bind",
        "Source": "/home/psy/test",
        "Destination": "/test",
        "Mode": "",
        "RW": true,
        "Propagation": "rprivate"
      }
    ],
    
  • 일단 volume랑 bind랑 비교해보면
    docker에서 관리해주냐가 다른점.
  • 직접 관리해주는 volume이 더 권장됨.

tmpgs mounts

  • 이 방법도 있는데
    container를 readonly로 만들고
    그 상태에서 뭔가 쓸 때 사용.
  • 암튼 상황이 어거지긴했음.
    그래서 굳이 안하기로함.

volume share

  • volume은 container끼리
    data를 공유가 가능하게 한다.
  • 같은 volume를 쓰면 됨.

    1
    2
    
    docker create --name test1 -i -t -v test_vol:/test centos:latest
    docker create --name test2 -i -t -v test_vol:/test centos:latest
    
  • Volume, Bind mounts 둘 다 상관없음

This post is licensed under CC BY 4.0 by the author.

Docker 3 - Container

Docker 5 - Exec / Attach

Comments powered by Disqus.