Loading... 前些时间有个前同事问我,为什么我的容器启动的Tomcat无法访问?他绝对是运维新秀,善于思考。不过以现在的互联网企业缩减速度,不知道现在学运维还有用吗?这个问题我也想过。既然选择了走这条路,这个方向。有一技再身,总比没有强吧,没背景,不学一些技术还能做什么?而且换个思路,文明离不开科技,未来科技总是会被需要的。接下去我们回过头来说一下关于容器启动的Tomcat无法访问的一些排查思路和技巧。 # 问题描述 ```bash docker run -it -p 3355:8088 tomcat /bin/bash #可以访问 docker run -it -p 3355:8080 tomcat /bin/bash #无法访问 # 制作镜像时候如果没有做HEALTHCHECK,那就算启动失败,容器也不会自动停止。所以不管能否访问,宿主机3355端口都会存在。 ``` 从上面的问题点可以看出来,映射到宿主机的端口都为3355,宿主机防火墙的可能性排除。其次为什么8088可以8080不行,很明显是镜像问题。但是docker官方镜像肯定是标准的8080。不过算了,不管是不是官方镜像进容器看看吧。 <img src="https://storage.bbcking5.com/文章内部图/自动/image-20240714224554206.png" alt="image-20240714224554206" style="zoom:50%;" style=""> # 查看端口号 ## 最常见的办法 既然8080不行,那我们启动容器后,执行 `docker exec -it tomcat /bin/bash` 进入容器一看究竟。先是使用`ss -nutlp` 命令查看一下当前端口,直接报错没这个命令。好吧那就换成`netstat -antlp` 看下吧,毕竟ss命令是iproute包中的,netstat是net-tool包中的,net-tool在所有Linux发行版中大多都会默认自带,甚至BSD一般默认也会带有这个包。但不幸的是,还是报错没这个命令。新人对Linux不熟,通常这两条命令就是全部,别无他法。 ## 对Linux深入理解后 我们知道Linux是一个一切皆文件的操作系统。文件中难道没有端口信息吗?答案肯定是有的嘛!我暂且就用一台有ss命令的Linux去做讲解的演示。演示以及理解后,相信自己也能够在没有命令协助下找到想要的端口。 ```bash # ps 或者 top 等命令都能查看进程号PID 为828 [root@test ~]# ps aux |grep ssh |grep -v grep root 828 0.0 0.4 112984 4356 ? Ss Jun20 0:00 /usr/sbin/sshd -D root 66427 0.0 0.5 158988 5640 ? Ss 07:16 0:00 sshd: root@pts/0,pts/1 # 查看828进程下句柄文件,有3个socket号。做网络编程的同学可能会比较熟悉socket是什么。 [root@test ~]# ll /proc/828/fd/ total 0 lr-x------. 1 root root 64 Jun 20 00:54 0 -> /dev/null lrwx------. 1 root root 64 Jun 20 00:54 1 -> socket:[18824] lrwx------. 1 root root 64 Jun 20 00:54 2 -> socket:[18824] lrwx------. 1 root root 64 Jun 20 00:54 3 -> socket:[18840] lrwx------. 1 root root 64 Jun 20 00:54 4 -> socket:[18849] # 查看tcp或者udp的状态文件(得看进程具体监听是哪个协议) [root@test ~]# cat /proc/828/net/tcp # 输出字段已缩减 sl local_address rem_address uid timeout inode 0: 00000000:14EB 00000000:0000 193 0 18956 1 ffff8d362f8c87c0 100 0 0 10 0 1: 00000000:0016 00000000:0000 0 0 18840 1 ffff8d362f8c8000 100 0 0 10 0 2: 0100007F:0019 00000000:0000 0 0 19478 1 ffff8d362f8c8f80 100 0 0 10 0 3: 3705A8C0:0016 02FAA8C0:FDB9 0 0 243038 4 ffff8d362d041740 20 4 27 10 -1 ``` 得到上述输出后,找到对应的socket号对应的是如下inode号。里面只有18840是对应的。注意力锁定到那一行,找到其中的 `local_address 为 00000000:0016` 。这其实就是以16进制表示的 `ip:port` 。把0016转成十进制 就等于 22。 ## 最终验证 使用ss命令把端口和进程号一起打印出来,发现的确ssh的pid为828,且端口号是tcp的22端口,监听的ip也是0.0.0.0所有ip,完全正确。 ```bash [root@test ~]# ss -nutlp |grep ssh tcp LISTEN 0 128 *:22 *:* users:(("sshd",pid=828,fd=3)) tcp LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=828,fd=4))```# ``` # 好像漏了啥 啊,前面说的容器的事情最后原因就是镜像问题镜像用的就是8088端口,绝对不是docker官方镜像,用8080端口后连进程都没起来。所以没有端口号,哈哈哈! ![](https://storage.bbcking5.com/文章内部图/自动/images.jpg) Last modification:July 15, 2024 © Allow specification reprint Like 如果觉得我的文章对你有用,请随意赞赏