맥에서 도커 컨테이너 실행 시, 포트 연결이 안될 수 있다. 내부망 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/