맥에서 도커 컨테이너 실행 시, 포트 연결이 안될 수 있다. 내부망 172.17.x.x 대역을 사용하는 환경에서 이슈가 존재한다. 도커는 디폴트로 172.17.0.0/16 대역을 사용하고 있다. 



gateway가 172.17.0.1이고 IPAddress가 172.17.0.2이라면 도커 컨테이너 실행시 포트 포워딩한다 해도 로컬 호스트에서 도커 포트로 연결이 안되는 문제가 발생된다. 


도커 기본 네트워크 환경을 변경한다. 다음 처럼 도커 기본 네트워크를 172.17.x.x. 대역이 아닌 192.168.x.x 대역으로 기본 구성을 변경한다. 


# cd ~/Library/Containers/com.docker.docker/Data/database

# git reset HEAD com.docker.driver.amd64-linux

Unstaged changes after reset:

D com.docker.driver.amd64-linux/disk/compact-after

D com.docker.driver.amd64-linux/disk/on-flush

D com.docker.driver.amd64-linux/disk/path

D com.docker.driver.amd64-linux/disk/size

D com.docker.driver.amd64-linux/disk/trim

D com.docker.driver.amd64-linux/etc/docker/daemon.json

D com.docker.driver.amd64-linux/etc/hostname

D com.docker.driver.amd64-linux/etc/ssl/certs/ca-certificates.crt

D com.docker.driver.amd64-linux/etc/sysctl.conf

D com.docker.driver.amd64-linux/expose-docker-socket

D com.docker.driver.amd64-linux/filesystem

D com.docker.driver.amd64-linux/hypervisor

D com.docker.driver.amd64-linux/insecure-registry

D com.docker.driver.amd64-linux/memory

D com.docker.driver.amd64-linux/memoryMiB

D com.docker.driver.amd64-linux/mounts

D com.docker.driver.amd64-linux/native/boot-protocol

D com.docker.driver.amd64-linux/native/port-forwarding

D com.docker.driver.amd64-linux/native/uefi-boot-disk

D com.docker.driver.amd64-linux/ncpu

D com.docker.driver.amd64-linux/network

D com.docker.driver.amd64-linux/on-sleep

D com.docker.driver.amd64-linux/proxy-system/exclude

D com.docker.driver.amd64-linux/proxy-system/http

D com.docker.driver.amd64-linux/proxy-system/https

D com.docker.driver.amd64-linux/proxy-verbose

D com.docker.driver.amd64-linux/proxy/exclude

D com.docker.driver.amd64-linux/proxy/http

D com.docker.driver.amd64-linux/proxy/https

D com.docker.driver.amd64-linux/proxy/mode

D com.docker.driver.amd64-linux/schema-version

D com.docker.driver.amd64-linux/slirp/dns

D com.docker.driver.amd64-linux/slirp/docker

D com.docker.driver.amd64-linux/slirp/domain

D com.docker.driver.amd64-linux/slirp/host

D com.docker.driver.amd64-linux/slirp/max-connections

D com.docker.driver.amd64-linux/slirp/mtu

D com.docker.driver.amd64-linux/state/last-shutdown-time

D com.docker.driver.amd64-linux/state/last-start-time

D com.docker.driver.amd64-linux/upgrade/experimental-debug

D com.docker.driver.amd64-linux/vmnet-simulate-failure


# git checkout -- com.docker.driver.amd64-linux


# vi com.docker.driver.amd64-linux/etc/docker/daemon.json

// {"debug":true,"experimental":true} 이렇게 되어 있는데.. 다음처럼 추가한다. 

{"debug":true,"experimental":true, "bip":"192.168.5.1/24"}



그 다음 Docker for mac 프로세스를 재시작한다. 



이제 확인해보자. 최신 docker를 사용 중인지 확인하고 테스트할 도커 이미지를 실행한다. 테스트할 도커 이미지는 springcloud/eureka이다. 



$ docker version

Client:

 Version:      17.09.0-ce

 API version:  1.32

 Go version:   go1.8.3

 Git commit:   afdb6d4

 Built:        Tue Sep 26 22:40:09 2017

 OS/Arch:      darwin/amd64


Server:

 Version:      17.09.0-ce

 API version:  1.32 (minimum version 1.12)

 Go version:   go1.8.3

 Git commit:   afdb6d4

 Built:        Tue Sep 26 22:45:38 2017

 OS/Arch:      linux/amd64

 Experimental: true

 





참고로 도커 컨테이너를 포그라운드 데몬하고 싶다면 다음 방식을 사용한다. 포트가 8761포트로 뜬 지 확인한다. 


이렇게 하면 포트 포워딩이 되지 않는다.


$ docker run springcloud/eureka

..

2017-10-20 02:35:42.958  INFO 1 --- [       Thread-4] c.n.eureka.PeerAwareInstanceRegistry     : Adding replica node: http://localhost:8761/eureka/

2017-10-20 02:35:43.025  INFO 1 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8761 (http)

2017-10-20 02:35:43.028  INFO 1 --- [           main] eurekademo.EurekaApplication             : Started EurekaApplication in 8.907 seconds (JVM running for 9.702)

2017-10-20 02:35:43.081  INFO 1 --- [       Thread-4] c.n.eureka.PeerAwareInstanceRegistry     : Updating the replica nodes as they seem to have changed from [] to [http://localhost:8761/eureka/]





-p 옵션을 주어야 동작할 수 있다. 8761포트를 8888포트로 연결할 마음으로  -p 8761:8888을 추가했다.

(따라하지 말고, 아래부터는 내용을 볼 것!!!)


$ docker run  -p 8761:8888  springcloud/eureka


-ti 옵션을 주면 조금 출력이 예뻐보인다. 


$ docker run  -p 8761:8888 -ti springcloud/eureka




백그라운드로 데몬을 실행하려면 다음을 사용한다. 


$ docker run  -p 8761:8888 -d springcloud/eureka




docker ps로 확인하니. 아래와 같이 나왔다. 



$ docker ps

CONTAINER ID        IMAGE                COMMAND                CREATED              STATUS              PORTS                              NAMES

a3938ad9745b        springcloud/eureka   "java -jar /app.jar"   About a minute ago   Up About a minute   8761/tcp, 0.0.0.0:8761->8888/tcp   focused_hopper




그러나 


8761, 8888 포트로 접근이 되지 않는다. 


$ curl localhost:8761/eureka/


$ curl localhost:8888/eureka/





확인해보기 위해 docker inspect를 실행해 보낟. 


$ docker inspect 도커-컨테이너-이름




네트워크만 보려면 다음 커맨드를 실행한다.  docker bridge 잘 있고. 네트워크도 192.168로 잘 설정되어 있다. 




$ docker network inspect bridge

[

    {

        "Name": "bridge",

        "Id": "13216e45817d9a5c15fffd0b77c732a65365129d49d1ed04fb8bbdc53c0ab348",

        "Created": "2017-10-27T06:33:11.783006123Z",

        "Scope": "local",

        "Driver": "bridge",

        "EnableIPv6": false,

        "IPAM": {

            "Driver": "default",

            "Options": null,

            "Config": [

                {

                    "Subnet": "192.168.5.1/24",

                    "Gateway": "192.168.5.1"

                }

            ]

        },

        "Internal": false,

        "Attachable": false,

        "Ingress": false,

        "ConfigFrom": {

            "Network": ""

        },

        "ConfigOnly": false,

        "Containers": {},

        "Options": {

            "com.docker.network.bridge.default_bridge": "true",

            "com.docker.network.bridge.enable_icc": "true",

            "com.docker.network.bridge.enable_ip_masquerade": "true",

            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",

            "com.docker.network.bridge.name": "docker0",

            "com.docker.network.driver.mtu": "1500"

        },

        "Labels": {}

    }

]





도커 컨테이너로 들어가도 잘 동작되는 것 같다. 


$ docker exec -it focused_hopper bash

root@6090234a5b33:/# 

root@6090234a5b33:/# ip addr

39: eth0@if40: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default

    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff

    inet 192.168.1.2/16 scope global eth0

       valid_lft forever preferred_lft forever

       



네트워크도 문제 없다. 

       

root@6090234a5b33:/# ip route

default via 172.17.0.1 dev eth0

172.17.0.0/16 dev eth0  proto kernel  scope link  src 172.17.0.2



내부에서 실행하면 동작이 잘된다. 


root@6090234a5b33:/#curl 172.17.0.2:8761

<!doctype html>

...





문제는 docker exec -p 옵션을 줄 때 반대로 주었다. 실제로 포트 포워딩할 포트가 앞에. 도커 컨테이너 포트는 뒤에 있어야 한다. 


docker -p "포트 포워딩할 포트:도커 컨테이너 포트" 이렇게 구성해야 한다. 이걸 모르고 삽질하고 있었다. 


다시 도커 컨테이너를 실행해본다. 



# docker run  -p 8888:8761 -d springcloud/eureka



# docker ps

CONTAINER ID        IMAGE                COMMAND                CREATED             STATUS              PORTS                    NAMES

75ba8624fff6        springcloud/eureka   "java -jar /app.jar"   6 seconds ago       Up 4 seconds        0.0.0.0:8888->8761/tcp   frosty_elion




# curl localhost:8888 하니 동작이 잘된다. 


docker port로 확인해보니 잘 동작한다. 


# docker port frosty_elion

8761/tcp -> 0.0.0.0:8888



lsof listen 포트 확인하니. 제대로 동작하는지 확인할 수 있었다. 


# lsof -iTCP -sTCP:LISTEN -n -P


vpnkit    21848 samuel.kim   20u  IPv4 0xb0df1cffacb7067      0t0  TCP *:8888 (LISTEN)

vpnkit    21848 samuel.kim   21u  IPv6 0xb0df1d003088737      0t0  TCP [::1]:8888 (LISTEN)





잘 동작한 것을 확인하고 도커 컨테이너를 내린다. 


$ docker stop frosty_elion




공부자료.

https://docs.docker.com/engine/userguide/networking/default_network/custom-docker0/

https://github.com/moby/moby/issues/25064

https://docs.docker.com/engine/reference/commandline/dockerd/




Posted by '김용환'

댓글을 달아 주세요