公司的微服务一直在VMware基础上新建了一堆VM主机,然后在主机上运行微服务,据网上的各类文章说微服务和Docker搭配起来使用效果最佳。关于Docker的概念就不介绍,这篇文章记录一下自己这几天的研究成果。前提,我在安装和使用docker的过程中,发现docker普通用户无权限操作,必须要切换为root账号。
一、安装Docker
yum install docker-ce
安装的版本如下
[root@rvc28n01 appadm]# docker -v
Docker version 20.10.18, build b40c2f6
新建环境配置文件,这个配置文件默认不存在,需要手工新建
mkdir -p /etc/docker/daemon.json
vim /etc/docker/daemon.json
{
"registry-mirrors": ["http://hub-mirror.c.163.com"],
"bip": "172.17.0.1/24"
}
这里面定义的是镜像加速和私网网段配置
systemctl daemon-reload
systemctl start docker.service
启动
安装完Docker后,我发现容器启动后无法与宿主机互相访问,要删除docker的虚拟网桥。详细查看这个链接:https://huaweicloud.csdn.net/63311951d3efff3090b51f7f.html?spm=1001.2101.3001.6650.10&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Eactivity-10-124520733-blog-126327633.pc_relevant_multi_platform_whitelistv6&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Eactivity-10-124520733-blog-126327633.pc_relevant_multi_platform_whitelistv6&utm_relevant_index=15
步骤如下:
需要先安装网桥管理工具包
yum install bridge-utils -y
1)检查网桥brctl show
[root@localhost ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.000000000000 no
2) 检查ip
[root@localhost ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eno16777736: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:85:de:4a brd ff:ff:ff:ff:ff:ff
inet 192.168.137.130/24 brd 192.168.137.255 scope global dynamic eno16777736
valid_lft 1627sec preferred_lft 1627sec
inet6 fe80::20c:29ff:fe85:de4a/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
link/ether 02:42:32:06:66:2d brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:32ff:fe06:662d/64 scope link
valid_lft forever preferred_lft forever
可以看到docker创建的虚拟网卡docker0的网段为172.17.0.1/16
3)查看路由: ip route
[root@localhost ~]# ip route
default via 192.168.137.2 dev eno16777736 proto static metric 100
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
192.168.137.0/24 dev eno16777736 proto kernel scope link src 192.168.137.130 metric 100
即172.17.0.0/16网段的包均通过docker0网桥来转发.
- 再来查看容器的ip: docker exec -it <容器名称> ip a
[root@localhost ~]# docker exec -it mn ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
129: eth0@if130: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:0a:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.0/16 brd 172.17.10.255 scope global eth0
valid_lft forever preferred_lft forever
可以看到虚拟网卡eth0的ip为172.17.0.0
- 查看容器内的路由: docker exec -it c_name ip route
[root@localhost ~]# docker exec -it mn ip route
default via 172.17.10.1 dev eth0
172.17.0.0/16 dev eth0 scope link src 172.17.0.1
由此可知172.17.0.0网段的包均走容器内的eth0,默认网关为172.17.10.1
- 如果容器中无法ping通外网,首先查看能否ping通网关。如果网关都无法ping通,说明网桥或网段有问题。这里就可以用tcpdump来查看。比如监控上面第一步的网桥接口tcpdump -i vethaef304e -nn,正常的网络包应答如下:bash-4.4# ping -c 1 8.8.8.8
[root@localhost ~]# tcpdump -i vethaef304e -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on vethaef304e, link-type EN10MB (Ethernet), capture size 262144 bytes
17:17:16.282976 IP 172.17.10.2 > 8.8.8.8: ICMP echo request, id 2304, seq 0, length 64
17:17:16.325812 IP 8.8.8.8 > 172.17.10.2: ICMP echo reply, id 2304, seq 0, length 64
17:17:21.297595 ARP, Request who-has 172.17.10.1 tell 172.17.10.2, length 28
17:17:21.297656 ARP, Reply 172.17.10.1 is-at f2:29:f4:5b:3d:f2, length 28
异常时就只有request who-has包,没有reply
- 问题解决
查看网桥,路由和ip均没发现问题,试试修改docker0的默认网段,居然成功了,步骤如下:
1) 删除原有配置
service docker stop
ip link set dev docker0 down
brctl delbr docker0
iptables -t nat -F POSTROUTING
- 创建新的网桥
brctl addbr docker0
ip addr add 172.17.10.1/24 dev docker0
ip link set dev docker0 up
- 修改docker配置,在/etc/docker/daemon.json中追加bip如下,注意json的格式,bip前面需要有,root@XXXXXX~# cat /etc/docker/daemon.json
vim /etc/docker/daemon.json
{
"insecure-registries":["x.x.x"],
"bip": "172.17.10.1/24"
}
4)重启docker: systemctl restart docker
[root@localhost ~]# systemctl restart docker
二、制作Dockerfile
镜像中我主要新建了一些必要的文件夹,安装了wget的命令库,添加jdk8的环境变量设置,暴露了内部的一些端口范围,我先做了一个基础镜像,然后在基础镜像没问题的前提中以这个为基础做了第二个应用镜像
基础镜像的配置文件
vim /app/Dockerfile
FROM centos:centos7
MAINTAINER lengye
RUN mkdir -p /app/comm && mkdir -p /app/logs && mkdir -p /app/temp
RUN yum -y install wget && yum clean all
COPY conf /app/conf/
COPY apps /app/apps/
WORKDIR /app/apps
ADD jdk1.8.0_112.tar.gz /app/comm
ENV JAVA_HOME /app/comm/jdk1.8.0_112
ENV JRE_HOME /app/comm/jdk1.8.0_112/jre
ENV PATH $JAVA_HOME/bin:$PATH
EXPOSE 30010-30020/tcp
保存配置文件,然后进入到/app中进行构建
docker build -t jdk8:1.0 /app
可以看到进行如下
[root@srvc28n01 imageDocker]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
jdk8 1.0 5fd2227f2cdd 8 hours ago 602MB
centos centos7 eeb6ee3f44bd 12 months ago 204MB
nginx 1.14-alpine 8a2fb25a19f5 3 years ago 16MB
对刚刚的镜像进行测试,看有没有问题,基于镜像运行一个容器,同时增加-rm参数,表示容器运行成功后就删除,最后添加要执行的shell命令,格式如下
docker run --name test --rm jdk8:1.0 ls /app/conf
[root@srvc28n01 appadm]# docker run --name test --rm jdk8:1.0 ls /app
apps
comm
conf
logs
temp
[root@srvc28n01 appadm]# docker run --name test --rm jdk8:1.0 ls /app/conf
d140de22-9eaf-404f-93ea-cff0cc6a4f19.p12
d140de22-9eaf-404f-93ea-cff0cc6a4f19.properties
env.properties
制作的镜像没问题,接下来继续制作微服务启动的配置文件,这里我使用了entrypoint,通过启动命令中传参给容器进行服务的启动,另我们的微服务都部署在远程服务仓库上,本地不存放服务,所以我这里不需要在Dockfile中进行ADD jar文件
vim /app/Dockerfile
FROM jdk8:1.0
MAINTAINER lengye
ENTRYPOINT ["java","-Xmx128m","-Xms128m","-Drocketmq.client.log.loadconfig=false","-jar","/app/apps/nhframework.boot.jar","start"]
保存配置文件,然后进入到/app中进行构建
docker build -t jdk8:1.0 /app
[root@srvc28n01 imageDocker]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
dockerenrty 2.3 7002ab63aa88 2 hours ago 602MB
三、启动容器
docker run --add-host=jars.services.info:10.50.10.6(我这边的远程服务仓库,一般用不到) --name test14(容器名称) dockerenrty:2.3 test-front 2.1.11-SNAPSHOT(服务变量传给容器内的entry) &
docker run --add-host=jars.services.info:10.50.10.6 --name test14 dockerenrty:2.3 test-front 2.1.11-SNAPSHOT &
10.50.10.6是指我这里的微服务jar包仓库,启动时自动从这上面获取服务的jar包并启动,所以容器本地不需要添加文件
--add-host=jars.services.info:10.50.10.6意思是将jars.services.info和10.50.10.6的对应关系加到/etc/hosts,我制作镜像的时候试了好多方法都不行,只能通过这种参数传递实现了
现在回头去看容器启动情况
[root@srvc28n01 imageDocker]# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
afaed1f324df dockerenrty:2.3 "java -Xmx128m -Xms1…" 7 minutes ago Up 7 minutes 30010-30020/tcp test14
备注:之前我们这边部署在VM主机上的时候,都是将启动命令写到shell脚本中,通过脚本启动服务。在制作docker容器的时候,我本来也想通过CMD直接调用脚本启动,但是发现不行,每次容器里面的启动脚本执行后就自动退出了,不会因为你脚本中有个java -jar的命令而保持开启,所以最后还是通过entrypoint的方式来启动微服务。