Docker的安装及使用原理

1.docker安装

此处安装在CentOS7中

https://docs.docker.com/install/linux/docker-ce/centos/

1、卸载之前的docker

sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine

2、安装必要的依赖

sudo yum install -y yum-utils \ device-mapper-persistent-data \ lvm2

3、设置docker仓库 【可以设置阿里云镜像仓库,也可以搭建自己docker hub】

sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo

阿里云镜像地址:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors

4、安装docker

sudo yum install -y docker-ce docker-ce-cli containerd.io

sudo yum install -y docker

5、启动docker

sudo systemctl start docker && sudo systemctl enable docker

6、测试docker安装是否成功

sudo docker run hello-world
# step 1: 安装必要的一些系统工具
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# Step 2: 添加软件源信息
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# Step 3: 更新并安装 Docker-CE
sudo yum makecache fast
sudo yum -y install docker-ce
# Step 4: 开启Docker服务
sudo service docker start

注意:其他注意事项在下面的注释中
# 官方软件源默认启用了最新的软件,您可以通过编辑软件源的方式获取各个版本的软件包。例如官方并没有将测试版本的软件源置为可用,你可以通过以下方式开启。同理可以开启各种测试版本等。
# vim /etc/yum.repos.d/docker-ce.repo
#   将 [docker-ce-test] 下方的 enabled=0 修改为 enabled=1
#
# 安装指定版本的Docker-CE:
# Step 1: 查找Docker-CE的版本:
# yum list docker-ce.x86_64 --showduplicates | sort -r
#   Loading mirror speeds from cached hostfile
#   Loaded plugins: branch, fastestmirror, langpacks
#   docker-ce.x86_64            17.03.1.ce-1.el7.centos            docker-ce-stable
#   docker-ce.x86_64            17.03.1.ce-1.el7.centos            @docker-ce-stable
#   docker-ce.x86_64            17.03.0.ce-1.el7.centos            docker-ce-stable
#   Available Packages
# Step2 : 安装指定版本的Docker-CE: (VERSION 例如上面的 17.03.0.ce.1-1.el7.centos)
# sudo yum -y install docker-ce-[VERSION]
# 注意:在某些版本之后,docker-ce安装出现了其他依赖包,如果安装失败的话请关注错误信息。例如 docker-ce 17.03 之后,需要先安装 docker-ce-selinux。
# yum list docker-ce-selinux- --showduplicates | sort -r
# sudo yum -y install docker-ce-selinux-[VERSION]

# 通过经典网络、VPC网络内网安装时,用以下命令替换Step 2中的命令
# 经典网络:
# sudo yum-config-manager --add-repo http://mirrors.aliyuncs.com/docker-ce/linux/centos/docker-ce.repo
# VPC网络:
# sudo yum-config-manager --add-repo http://mirrors.could.aliyuncs.com/docker-ce/linux/centos/docker-ce.repo
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://hab4tvxa.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

2.docker基本使用

  • tomcat

    • 下载 image
    docker pull tomcat
    

    docker pull 拉取镜像到本地

    • 创建 container
    docker run -d --name mytomcat -p 9090:8080 tomcat
    

    docker run 根据某个镜像创建容器

    -d 让容器在后台运行,其实就是一个进程

    --name 给容器指定一个名字

    -p 将容器的端口映射到宿主机的端口

    • 进入容器里面
    docker exec -it mytomcat /bin/bash
    

    docker exec -it 进入到某个容器中并交互式运行

  • mysql

    docker run -d --name my-mysql -p 3301:3306 -e MYSQL_ROOT_PASSWORD=123456 -- privileged mysql
    

    MYSQL_ROOT_PASSWORD 设置root用户密码

注:

docker pull 默认是在hub.docker.com 上拉取image

docker pull tomcat拉取的image默认是最新的版本,可以在后面指定版本":"

3.Image

Image就是由一层一层的layer组成的。

3.1.官方Image

https://github.com/docker-library

此处参考官方mysql image

mysql:https://github.com/docker-library/tomcat/blob/master/8.5/jdk8/openjdk/Dockerfifile

3.2.Dockerfile

通过Dockerfile可以制作自己的镜像

3.2.1.FROM

指定基础镜像,比如FROM ubuntu:14.04

FROM ubuntu:14.04

3.2.2.RUN

在镜像内部执行一些命令,比如安装软件,配置环境等,换行可以使用"\"

RUN groupadd -r mysql && useradd -r -g mysql mysql

3.2.3.ENV

设置变量的值,比如ENV MYSQL_MAJOR 5.7,可以通过docker run --e key=value修改,后面可以直接使用${MYSQL_MAJOR}

ENV MYSQL_MAJOR 5.7

3.2.4.LABEL

设置镜像标签

LABEL email="itcrazy2016@163.com" 
LABEL name="itcrazy2016"

3.2.5.VOLUME

指定数据的挂在目录

VOLUME /var/lib/mysql

3.2.6.COPY

将主机的文件复制到镜像内,如果目录不存在,会自动创建所需要的目录,注意只是复制,不会提取和解压

COPY docker-entrypoint.sh /usr/local/bin/

3.2.7.ADD

将主机的文件复制到镜像内,和COPY类似,只是ADD会对压缩文件提取和解压

ADD application.yml /usr/local/

3.2.8.WORKDIR

指定镜像的工作目录,之后的命令都是基于此目录工作,若不存在则创建

WORKDIR /usr/local 
WORKDIR tomcat 
RUN touch test.txt

会在/usr/local/tomcat下创建test.txt文件

WORKDIR /root ADD app.yml test/

会在/root/test下多出一个app.yml文件

3.2.9.CMD

容器启动的时候默认会执行的命令,若有多个CMD命令,则最后一个生效

CMD ["mysqld"]
或
CMD mysqld

3.2.10.ENTRYPOINT

和CMD的使用类似

ENTRYPOINT ["docker-entrypoint.sh"]

和CMD的不同的是,docker run执行时,会覆盖CMD的命令,而ENTRYPOINT不会

3.2.11.EXPOSE

指定镜像要暴露的端口,启动镜像时,可以使用-p将该端口映射给宿主机

EXPOSE 3306

3.3.Dockerfile实战Springboot项目

(1) 创建一个Spring Boot项目

(2) 写一个controller

@RestController 
public class DockerController { 
    @GetMapping("/dockerfile") 
    @ResponseBody 
    String dockerfile() { 
    return "hello docker" ; 
    } 
} 

(3) mvn clean package打成一个jar包

在target下找到"dockerfile-demo-0.0.1-SNAPSHOT.jar"

(4) 在docker环境中新建一个目录"first-dockerfile"

(5) 上传"dockerfile-demo-0.0.1-SNAPSHOT.jar"到该目录下,并且在此目录创建Dockerfile

(6) 创建Dockerfile文件,编写内容

FROM openjdk:8 
MAINTAINER itcrazy2016 
LABEL name="dockerfile-demo" version="1.0" author="itcrazy2016" 
COPY dockerfile-demo-0.0.1-SNAPSHOT.jar dockerfile-image.jar 
CMD ["java","-jar","dockerfile-image.jar"] 

(7) 基于Dockerfile构建镜像

docker build -t test-docker-image .

(8) 基于image创建container

docker run -d --name user01 -p 6666:8080 test-docker-image 

(9) 查看启动日志docker logs user01

(10) 宿主机上访问curl localhost:6666/dockerfile

hello docker

(11) 还可以再次启动一个

docker run -d --name user02 -p 8081:8080 test-docker-image 

4.镜像仓库

4.1.docker hub

hub.docker.com 登录

(1) 在docker机器上登录

docker login 

(2) 输入用户名和密码

(3) docker push itcrazy2018/test-docker-image

​ [注意镜像名称要和docker id一致,不然push不成功]

(4) 给image重命名,并删除掉原来的

docker tag test-docker-image itcrazy2018/test-docker-image 

docker rmi -f test-docker-image 

(5) 再次推送,刷新hub.docker.com后台,发现成功

(6) 别人下载,并且运行

docker pull itcrazy2018/test-docker-image 

docker run -d --name user01 -p 6661:8080 itcrazy2018/test-docker-image

4.2.阿里云docker hub

阿里云docker仓库

https://cr.console.aliyun.com/cn-hangzhou/instances/repositories

参考手册

https://cr.console.aliyun.com/repository/cn-hangzhou/dreamit/image-repo/details

(1) 登录到阿里云docker仓库

sudo docker login --username=冷酷少爷kk registry.cn-hangzhou.aliyuncs.com 

(2) 输入密码

(3) 创建命名空间,比如itcrazy2016

(4) 给image打tag

sudo docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/itcrazy2016/test- 
docker-image:v1.0 

(5)推送镜像到docker阿里云仓库

sudo docker push registry.cn-hangzhou.aliyuncs.com/itcrazy2016/test-docker- 
image:v1.0 

(6)别人下载,并且运行

docker pull registry.cn-hangzhou.aliyuncs.com/itcrazy2016/test-docker- 
image:v1.0 

docker run -d --name user01 -p 6661:8080 registry.cn- 
hangzhou.aliyuncs.com/itcrazy2016/test-docker-image:v1.0

4.3.搭建自己的Docker Harbor

(1) 访问github上的harbor项目

https://github.com/goharbor/harbor

(2) 下载版本,比如1.7.1

https://github.com/goharbor/harbor/releases

(3) 找一台安装了docker-compose[这个后面的课程会讲解],上传并解压

tar -zxvf xxx.tar.gz

(4) 进入到harbor目录

修改harbor.cfg文件,主要是ip地址的修改成当前机器的ip地址

同时也可以看到Harbor的密码,默认是Harbor12345

(5) 安装harbor,需要一些时间

sh install.sh

(6)浏览器访问,比如39.100.39.63,输入用户名和密码即可

5.Image常见操作

(1) 查看本地image列表

docker images

docker image ls

(2) 获取远端镜像

docker pull

(3) 删除镜像[注意此镜像如果正在使用,或者有关联的镜像,则需要先处理完]

docker image rm imageid

docker rmi -f imageid

docker rmi -f $(docker image ls) 删除所有镜像

(4)运行镜像

docker run image

(5)发布镜像

docker push

6.Container

理解 :其实可以理解为container只是基于image之后的layer而已,也就是可以通过docker run image 创建出一个container出来。

6.1.container到image

既然container是基于image之上的,想想是否能够由一个container反推出image呢?

肯定是可以的,比如通过docker run运行起一个container出来,这时候对container对一些修改,然后再生成一个新的image,这时候image的由来就不仅仅只能通过Dockerfile咯。

实验:

(1) 拉取一个centos image

docker pull centos

(2) 根据centos镜像创建出一个container

docker run -d -it --name my-centos centos

(3) 进入my-centos容器中

docker exec -it my-centos bash

(4) 输入vim命令

bash: vim: command not found

(5) 我们要做的是:对该container进行修改,也就是安装一下vim命令,然后将其生成一个新的centos

(6) 在centos的container中安装vim

yum install -y vim

(7) 退出容器,将其生成一个新的centos,名称为"vim-centos-image"

docker commit my-centos vim-centos-image

(8) 查看镜像列表,并且基于"vim-centos-image"创建新的容器

docker run -d -it --name my-vim-centos vim-centos-image

(9) 进入到my-vim-centos容器中,检查vim命令是否存在

docker exec -it my-vim-centos bash

vim

结论 :可以通过docker commit命令基于一个container重新生成一个image,但是一般得到 image 的方式不建议这么做,不然image怎么来的就全然不知咯。

6.2.container资源限制

如果不对container的资源做限制,它就会无限制地使用物理机的资源,这样显然是不合适的。

查看资源情况 :docker stats

6.2.1.内存限制

# --memory Memory limit 
# 如果不设置 --memory-swap,其大小和memory一样 
docker run -d --memory 100M --name tomcat1 tomcat

6.2.2.CPU限制

# --cpu-shares 权重 
docker run -d --cpu-shares 10 --name tomcat2 tomcat

6.2.3.图形化资源监控

https://github.com/weaveworks/scope

sudo curl -L git.io/scope -o /usr/local/bin/scope 
sudo chmod a+x /usr/local/bin/scope 
scope launch 39.100.39.63
# 停止scope 
scope stop 
# 同时监控两台机器,在两台机器中分别执行如下命令
scope launch ip1 ip2

6.3.container常见操作

(1) 根据镜像创建容器

docker run -d --name -p 9090:8080 my-tomcat tomcat

(2) 查看运行中的container

docker ps

(3) 查看所有的container[包含退出的]

docker ps -a

(4) 删除container

docker rm containerid

docker rm -f $(docker ps -a) 删除所有container

(5) 进入到一个container中

docker exec -it container bash

(6) 根据container生成image

docker commit containerid imageid

(7) 查看某个container的日志

docker logs container

(8) 查看容器资源使用情况

docker stats

(9) 查看容器详情信息

docker inspect container

(10) 停止/启动容器

docker stop/start container

7.底层技术支持

Container是一种轻量级的虚拟化技术,不用模拟硬件创建虚拟机。

Docker是基于Linux Kernel的Namespace、CGroups、UnionFileSystem等技术封装成的一种自定义容器格式,从而提供一套虚拟运行环境。

Namespace:用来做隔离的,比如pid[进程]、net[网络]、mnt[挂载点]等

CGroups: Controller Groups用来做资源限制,比如内存和CPU等

Union file systems:用来做image和container分层

8.Docker网络

8.1.Linux中网卡

  • 查看网卡

    ip link show
    
    ls /sys/class/net
    
    ip a
    
    ifconfig
    
  • ip a 解读

    状态:UP/DOWN/UNKOWN等

    link/ether:MAC地址

    inet:绑定的IP地址

  • 配置文件

    在Linux中网卡对应的其实就是文件,所以找到对应的网卡文件即可

    比如:cat /etc/sysconfifig/network-scripts/ifcfg-eth0

  • 给网卡添加ip地址
    当然,这块可以直接修改ifcfg-*文件,但是我们通过命令添加试试

    (1)添加ip地址
    ip addr add 192.168.0.100/24 dev eth0 
    
    (2)删除IP地址
    ip addr delete 192.168.0.100/24 dev eth0
    
  • 网卡启动与关闭

    重启网卡 :

    service network restart / systemctl restart network 
    

    启动/关闭某个网卡 :

    ifup/ifdown eth0 or ip link set eth0 up/down 
    

8.2.Network Namespace

在linux上,网络的隔离是通过network namespace来管理的,不同的network namespace是互相隔离的

ip netns list:查看当前机器上的network namespace

network namespace的管理

ip netns list #查看 
ip netns add ns1 #添加 
ip netns delete ns1 #删除

8.2.1.namespace实战

(1) 创建一个network namespace

ip netns add ns1

(2) 查看该namespace下网卡的情况

ip netns exec ns1 ip a

(3) 启动ns1上的lo网卡

ip netns exec ns1 ifup lo

or

ip netns exec ns1 ip link set lo up

(4) 再次查看

可以发现state变成了UNKOWN

ip netns exec ns1 ip a

(5) 再次创建一个network namespace

ip netns add ns2

(6) 此时想让两个namespace网络连通起来

veth pair :Virtual Ethernet Pair,是一个成对的端口,可以实现上述功能

(7) 创建一对link,也就是接下来要通过veth pair连接的link

ip link add veth-ns1 type veth peer name veth-ns2

(8) 查看link情况

ip link

(9) 将veth-ns1加入ns1中,将veth-ns2加入ns2中

ip link set veth-ns1 netns ns1

ip link set veth-ns2 netns ns2

(10) 查看宿主机和ns1,ns2的link情况

ip link

ip netns exec ns1 ip link

ip netns exec ns2 ip link

(11) 此时veth-ns1和veth-ns2还没有ip地址,显然通信还缺少点条件

ip netns exec ns1 ip addr add 192.168.0.11/24 dev veth-ns1

ip netns exec ns2 ip addr add 192.168.0.12/24 dev veth-ns2

(12) 再次查看,发现state是DOWN,并且还是没有IP地址

ip netns exec ns1 ip link

ip netns exec ns2 ip link

(13) 启动veth-ns1和veth-ns2

ip netns exec ns1 ip link set veth-ns1 up

ip netns exec ns2 ip link set veth-ns2 up

(14) 再次查看,发现state是UP,同时有IP

ip netns exec ns1 ip a

ip netns exec ns2 ip a

(15) 此时两个network namespace互相ping一下,发现是可以ping通的

ip netns exec ns1 ping 192.168.0.12

ip netns exec ns2 ping 192.168.0.11

8.2.2.Container的NS

按照上面的描述,实际上每个container,都会有自己的network namespace,并且是独立的,我们可以进入到容器中进行验证

(1) 不妨创建两个container看看?

docker run -d --name tomcat01 -p 8081:8080 tomcat

docker run -d --name tomcat02 -p 8082:8080 tomcat

(2) 进入到两个容器中,并且查看ip

docker exec -it tomcat01 ip a

docker exec -it tomcat02 ip a

(3) 互相ping一下是可以ping通的

值得我们思考的是,此时tomcat01和tomcat02属于两个network namespace,是如何能够ping通的?

有些小伙伴可能会想,不就跟上面的namespace实战一样吗?注意这里并没有veth-pair技术

8.3.深入分析container网络-Bridge

8.3.1.docker0默认bridge

(1) centos的网络:ip a,可以发现

4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
link/ether 02:42:43:7b:1b:bd 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:43ff:fe7b:1bbd/64 scope link 
valid_lft forever preferred_lft forever 

8: veth3b72761@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 
state UP group default 
link/ether 22:a3:13:4d:7f:29 brd ff:ff:ff:ff:ff:ff link-netnsid 2 
inet6 fe80::20a3:13ff:fe4d:7f29/64 scope link 
valid_lft forever preferred_lft forever 

(2) 查看容器tomcat01的网络:docker exec -it tomcat01 ip a,可以发现

[root@bogon ~]# docker exec -it tomcat01 ip a 
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 
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 

7: eth0@if8: <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 link-netnsid 0 
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 
valid_lft forever preferred_lft forever 

(3) 在centos中ping一下tomcat01的网络,发现可以ping通

ping 172.17.0.2 
[root@bogon ~]# ping 172.17.0.2 
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data. 
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.120 ms 
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.060 ms 
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.056 ms 

(4) 既然可以ping通,而且centos和tomcat1又属于不同的network namespace,是怎么连接的?

很显然,跟之前的实战是一样的,画个图

(5) 也就是说,在tomcat01中有一个eth0和centos的docker0中有一个veth3是成对的,类似于之前实战中的 veth-ns1和veth-ns2,不妨再通过一个命令确认下:brctl

安装一下:
yum install bridge-utils 

brctl show

(6) 那为什么tomcat01和tomcat02能ping通呢?不多说,直接上图

(7) 这种网络连接方法我们称之为Bridge,其实也可以通过命令查看docker中的网络模式:docker network ls ,bridge也是docker中默认的网络模式

(8) 不妨检查一下bridge:docker network inspect bridge

"Containers": { "6ad312b32f62b48935f3c95c58ae061df710bfebbd3d721b467507b9516eeb81": { 
"Name": "tomcat02", "EndpointID": "aa9c612c79f867e874d0cae1aab45374373b61e9cdbe79925d07ae2e89a1cca0", "MacAddress": "02:42:ac:11:00:03", "IPv4Address": "172.17.0.3/16", "IPv6Address": "" },"f49fc396d8e04f2b330163d91bb5d1482715202b4e2fd0c7f42833722787742a": { "Name": "tomcat01", "EndpointID": "c5440b063e8fc0c9c44f3f61bf68f577283417eb23cfa9a361d37973d01a8ba5", "MacAddress": "02:42:ac:11:00:02", "IPv4Address": "172.17.0.2/16", "IPv6Address": "" } }

(6) 在tomcat01容器中是可以访问互联网的,顺便把这张图画一下咯,NAT是通过iptables实现的

8.3.2.创建自己的network

(1) 创建一个network,类型为bridge

docker network create tomcat-net

or

docker network create --subnet=172.18.0.0/24 tomcat-net

(2) 查看已有的network:docker network ls

NETWORK ID NAME DRIVER SCOPE 

a1aa0d802154 bridge bridge local 

058b2ea4bf85 host host local 

0604ff19e224 none null local 

3012e3afd264 tomcat-net bridge local 

(3) 查看tomcat-net详情信息:docker network inspect tomcat-net

(4) 创建tomcat的容器,并且指定使用tomcat-net

docker run -d --name custom-net-tomcat --network tomcat-net tomcat

(5) 查看custom-net-tomcat的网络信息

docker exec -it custom-net-tomcat ip a

(6) 查看网卡信息

ip a

(7) 查看网卡接口

brctl show

bridge   name   bridge   id   STP enabled    interfaces 

br-3012e3afd264 8000.02429780e75d no vethf223a4b 

docker0 8000.0242437b1bbd no veth3b72761 

veth9d8c470 

(8) 此时在custom-net-tomcat容器中ping一下tomcat01的ip会如何?发现无法ping通

docker exec -it custom-net-tomcat ping 172.17.0.2 

PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data. 

^C

--- 172.17.0.2 ping statistics --- 

4 packets transmitted, 0 received, 100% packet loss, time 3000ms 

(9) 此时如果tomcat01容器能够连接到tomcat-net上应该就可以咯

docker network connect tomcat-net tomcat01

(10) 查看tomcat-net网络,可以发现tomcat01这个容器也在其中

(11) 此时进入到tomcat01或者custom-net-tomcat中,不仅可以通过ip地址ping通,而且可以通过名字ping到,这时候因为都连接到了用户自定义的tomcat-net bridge上

docker exec -it tomcat01 bash 
root@f49fc396d8e0:/usr/local/tomcat# ping 172.18.0.2 
PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data.
64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.048 ms 
64 bytes from 172.18.0.2: icmp_seq=2 ttl=64 time=0.040 ms
root@f49fc396d8e0:/usr/local/tomcat# ping custom-net-tomcat PING custom-net-tomcat
(172.18.0.2) 56(84) bytes of data. 64 bytes from custom-net-tomcat.tomcat-net
(172.18.0.2): icmp_seq=1 ttl=64 time=0.030 ms 64 bytes from custom-net-tomcat.tomcat-net
(172.18.0.2): icmp_seq=2 ttl=64 time=0.264 ms

但是ping tomcat02是不通的

root@f49fc396d8e0:/usr/local/tomcat# ping 172.17.0.3 
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data. 
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.045 ms 
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.066 ms
root@f49fc396d8e0:/usr/local/tomcat# ping tomcat02 
PING tomcat02 (220.250.64.26) 56(84) bytes of data.

8.4.深入分析Container网络-Host & None

  • Host

    (1) 创建一个tomcat容器,并且指定网络为none

    docker run -d --name my-tomcat-host --network host tomcat

    (2)查看ip地址

    docker exec -it my-tomcat-host ip a

    可以发现和centos是一样的

    (3) 检查host网络

    "Containers": { 
        "e1f00d47db344b6688e99c0f5b393e232309fbe1a4d9c3fc3e1ce7c107f3312d": { 
        "Name": "my-tomcat-host", 
        "EndpointID": 
        "f08456d9dca024cf6f911f8d32329ba2587ea89554c96b77c32698ace6998525", 
        "MacAddress": "", 
        "IPv4Address": "", 
        "IPv6Address": "" 
        } 
    } 
    
  • None

    (1) 创建一个tomcat容器,并且指定网络为none

    docker run -d --name my-tomcat-none --network none tomcat

    (2) 查看ip地址

    docker exec -it my-tomcat-none ip a

    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 
    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 
    

    (3) 检查none网络

    "Containers": { 
        "bb3f0db4fa76a25b5377da9c3bbf087ac7ef0de0a3f9c37a4ae959983d33105c": { 
        "Name": "my-tomcat-none", 
        "EndpointID": 
        "26055c08c968f9d6d03d10b3b66dfea004c35f5d2bd4067a2306566973e92f9e", 
        "MacAddress": "", 
        "IPv4Address": "", 
        "IPv6Address": "" 
        } 
    } 
    
    

8.5.端口映射及折腾

  • 端口映射

    (1) 创建一个tomcat容器,名称为port-tomcat

    docker run -d --name port-tomcat tomcat

    (2) 思考一下要访问该tomcat怎么做?肯定是通过ip:port方式

    docker exec -it port-tomcat bash

    curl localhost:8080

    (3) 那如果要在centos7上访问呢?

    docker exec -it port-tomcat ip a ---->得到其ip地址,比如172.17.0.4

    curl 172.17.0.4:8080

    小结之所以能够访问成功,是因为centos上的docker0连接了port-tomcat的network namespace

    (4) 那如果要在centos7通过curl localhost方式访问呢?显然就要将port-tomcat的8080端口映射到centos上

    docker rm -f port-tomcat

    docker run -d --name port-tomcat -p 8090:8080 tomcat

    curl localhost:8090

  • 折腾

    (1) centos7是运行在win10上的虚拟机,如果想要在win10上通过ip:port方式访问呢?

    #此时需要centos和win网络在同一个网段,所以在Vagrantfile文件中 
    
    #这种方式等同于桥接网络。也可以给该网络指定使用物理机哪一块网卡,比如 
    
    #config.vm.network"public_network",:bridge=>'en1: Wi-Fi (AirPort)' 
    
    config.vm.network"public_network" 
    
    centos7: ip a --->192.168.8.118 
    
    win10:浏览器访问 192.168.8.118:9080 
    

    (2) 如果也想把centos7上的8090映射到win10的某个端口呢?然后浏览器访问localhost:port

    #此时需要将centos7上的端口和win10上的端口做映射 
    
    config.vm.network"forwarded_port",guest:8098,host:8090 
    
    #记得vagrant reload生效一下 
    
    win10:浏览器访问 localhost:8098 
    

9.Docker数据持久化

9.1.Volume

(1) 创建mysql数据库的container

docker run -d --name mysql01 -e MYSQL_ROOT_PASSWORD=jack123 mysql

(2) 查看volume

docker volume ls

(3) 具体查看该volume

docker volume inspect

48507d0e7936f94eb984adf8177ec50fc6a7ecd8745ea0bc165ef485371589e8

(4) 名字不好看,name太长,修改一下

"-v mysql01_volume:/var/lib/mysql"表示给上述的volume起一个能识别的名字

docker run -d --name mysql02 -v mysql01_volume:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=jack123 mysql

(5) 查看volume

docker volume ls

docker volume inspect mysql01_volume

(6)真的能够持久化保存数据吗?不妨来做个实验

# 进入容器中
docker exec -it mysql01 bash
# 登录mysql服务 
mysql -uroot -pjack123 
# 创建测试库 
create database db_test 
# 退出mysql服务,退出mysql container 
# 删除mysql容器 
docker rm -f mysql01
# 查看volume
docker volume ls 
# 发现volume还在 
DRIVER VOLUME NAME 
local mysql01_volume

# 新建一个mysql container,并且指定使用"mysql01_volume" 
docker run -d --name test-mysql -v mysql01_volume:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=jack123 mysql 
# 进入容器,登录mysql服务,查看数据库
docker exec -it test-mysql bash 
mysql -uroot -pjack123 
show database; 
# 可以发现db_test仍然在 
| information_schema | 
| db_test |
| mysql |
| performance_schema | 
| sys

9.2.Bind Mounting

(1) 创建一个tomcat容器

docker run -d --name tomcat01 -p 9090:8080 -v /tmp/test:/usr/local/tomcat/webapps/test tomcat

(2) 查看两个目录

centos:cd /tmp/test tomcat容器:cd /usr/local/tomcat/webapps/test

(3) 在centos的/tmp/test中新建1.html,并写一些内容

<p style="color:blue; font-size:20pt;">This is p!</p>

(4) 进入tomcat01的对应目录查看,发现也有一个1.html,并且也有内容

(5) 在centos7上访问该路径:curl localhost:9090/test/1.html

(6) 在win浏览器中通过ip访问

10.Docker Compose

官网https://docs.docker.com/compose/

10.1.业务背景

10.2.Docker传统方式实现

10.2.1. 写Python代码&build image

(1)创建文件夹

mkdir -p /tmp/composetest
cd /tmp/composetest

(2)创建app.py文件,写业务内容

import time

import redis
from flask import Flask

app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)

def get_hit_count():
    retries = 5
    while True:
        try:
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)

@app.route('/')
def hello():
    count = get_hit_count()
    return 'Hello World! I have been seen {} times.\n'.format(count)

(3)新建requirements.txt文件

flask
redis

(4)编写Dockerfile

FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP app.py
ENV FLASK_RUN_HOST 0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . .
CMD ["flask", "run"]

(5)根据Dockerfile生成image

docker build -t python-app-image .

(6)查看images:docker images

python-app-image latest 7e1d81f366b7 3 minutes ago  213MB

10.2.2. 获取Redis的image

docker pull redis:alpine

10.2.3.创建两个container

(1)创建网络

docker network ls
docker network create --subnet=172.20.0.0/24 app-net 

(1)创建python程序的container,并指定网段和端口

docker run -d --name web -p 5000:5000 --network app-net python-app-image

(2)创建redis的container,并指定网段

docker run -d --name redis --network app-net redis:alpine

10.2.4.访问测试

ip[centos]:5000

10.3.简介和安装

10.3.1. 简介

官网https://docs.docker.com/compose/

Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration.

10.3.2.安装

Linux环境中需要单独安装

官网https://docs.docker.com/compose/install/

sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

10.4.docker compose实现

referencehttps://docs.docker.com/compose/gettingstarted/

10.4.1.同样的前期准备

新建目录,比如composetest

进入目录,编写app.py代码

创建requirements.txt文件

编写Dockerfile

10.4.2.编写docker-compose.yaml文件

默认名称,当然也可以指定,docker-compose.yaml

version: '3'
services:
  web:
    build: .
    ports:
      - "5000:5000"
    networks:
      - app-net

  redis:
    image: "redis:alpine"
    networks:
      - app-net

networks:
  app-net:
    driver: bridge

(1)通过docker compose创建容器

docker-compose up -d

(2)访问测试

10.5.详解docker-compose.yml文件

(1)version: '3'

表示docker-compose的版本

(2)services

一个service表示一个container

(3)networks

相当于docker network create app-net

(4)volumes

相当于-v v1:/var/lib/mysql

(5)image

表示使用哪个镜像,本地build则用build,远端则用image

(6)ports

相当于-p 8080:8080

(7)environment

相当于-e 

10.6.docker-compose常见操作

(1)查看版本

​ docker-compose version

(2)根据yml创建service

​ docker-compose up

​ 指定yaml:docker-compose up -f xxx.yaml

​ 后台运行:docker-compose up

(3)查看启动成功的service

​ docker-compose ps

​ 也可以使用docker ps

(4)查看images

​ docker-compose images

(5)停止/启动service

​ docker-compose stop/start

(6)删除service[同时会删除掉network和volume]

​ docker-compose down

(7)进入到某个service

​ docker-compose exec redis sh

10.7.scale扩缩容

(1)修改docker-compose.yaml文件,主要是把web的ports去掉,不然会报错

version: '3'
services:
  web:
    build: .
    networks:
      - app-net

  redis:
    image: "redis:alpine"
    networks:
      - app-net

networks:
  app-net:
    driver: bridge

(2)创建service

docker-compose up -d

(3)若要对python容器进行扩缩容

docker-compose up --scale web=5 -d
docker-compose ps
docker-compose logs web
posted @ 2022-03-22 12:40  无上桎梏  阅读(123)  评论(0编辑  收藏  举报