Docker介绍

Docker是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。

文档地址:https://docs.docker.com/

仓库地址:https://hub.docker.com/

Docker入门

基本概念

Docker基本组成:

Cover image for Getting Started with Docker for Developers

镜像 image

docker 镜像好比一个模板,可以通过这个目标创建容器服务。比如:nginx镜像 ===》run命令 ===》nginx01容器(提供服务)

容器 container

docker利用容器技术,独立运行一个或一组应用。容器是通过镜像创建的。

容器基本命令有:启动、停止、删除

仓库 repository

仓库是用来存放镜像的地方。

仓库可以分为:共有仓库、私有仓库。

Docker安装

Debian系统安装:

官方文档:https://docs.docker.com/engine/install/

# 卸载旧版本
apt-get remove docker docker-engine docker.io containerd runc

# 安装相关依赖和工具
apt-get install -y apt-transport-https ca-certificates curl gnupg lsb-release software-properties-common

# ######我们用阿里云替换官方###########
# 添加阿里云GPG key  https://mirrors.aliyun.com/docker-ce/linux/debian/
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/debian/gpg | apt-key add -
# 写入软件源信息
add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/debian $(lsb_release -cs) stable"

# ####默认使用官方源下载,####
# 添加Docker官方GPG key
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# 写入软件源信息
echo \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \
  $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null

# 安装Docker
apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io

# 配置镜像加速 可以在阿里云中的容器镜像服务下的镜像加速器替换"https://xxxxx.mirror.aliyuncs.com"
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://xxxxx.mirror.aliyuncs.com"]
}
EOF

# 重启docker
systemctl daemon-reload
systemctl restart docker

image-20210316003906890

Docker常用命令

常用命令一览图:
docker-command.png

文档地址:https://docs.docker.com/engine/reference/commandline/docker/

帮助命令

# 查看版本
docker version

# 查看docker信息
docker info

# 查看命令的帮助信息
docker 命令 --help

docker search

通过Docker Hub搜索Docker镜像。一般用的不是很多,可以直接通过Docker Hub中进行搜索。

## 搜索redis镜像
docker search redis

docker_search.png

docker pull

从远程仓库拉取一个镜像。可以不用指定tag名称,则用latest,不过一般建议都带上指定tag

## 获取redis镜像,不带tag,默认latest
docker pull redis

## 获取redis镜像,带tag,指定具体tag
docker pull redis:6.2.1-alpine

docker_pull.png

docker images

列出本地镜像。

docker images

docker_images.png

docker rmi

删除一个或多个镜像。
docker_images_result.png

## 通过REPOSITORY和TAG名删除镜像
docker rmi redis:6.2.1-alpine

## 通过IMAGE ID删除镜像
docker rmi 621ceef7494a

docker_rmi.png

docker run

创建一个新的容器并运行一个命令。
语法:

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

常用OPTIONS说明:

  • -d: 后台运行容器,并返回容器ID;
  • -i: 以交互模式运行容器,通常与 -t 同时使用;
  • -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
  • -P: 大写P。随机端口映射,容器内部端口随机映射到主机的端口;
  • -p: 小写p指定端口映射,格式为:主机(宿主)端口:容器端口;
  • --name: 为容器指定一个名称;
  • -e: 设置环境变量;
  • -v--volume: 绑定一个卷;
  • -h: 指定容器host name;
docker run --name nginx01 -p 80:80 -v /data:/data -d nginx:latest
# --name 将启动的容器命名为nginx01
# -p 将容器80端口映射到主机80端口
# -v 将主机/data目录映射到容器/data目录
# -d 以后台模式启动

docker ps

列出容器。

docker ps

docker_ps.png

docker top

查看容器中的进程信息。

docker top 容器id

docker logs

获取容器日志。
docker_logs.png

docker startdocker stopdocker restart

docker start: 启动一个或多个已停止的容器;
docker stop: 停止一个或多个正在运行的容器;
docker restart: 重启一个或多个容器。

docker attach

连接到正在运行中的容器。

docker exec   # 连接容器后开启一个新的终端(常用)
docker attach   # 连接容器后,进入正在执行的终端,不会启动新的进程。

docker rm

删除一个或多个容器。
docker_rm.png

docker rm 容器id   # 删除指定容器。正常情况不允许删除正在运行的容器
docker rm -f $(docker ps -aq)   # 删除所有容器
docker ps -a -q|xargs docker rm   # 删除所有容器

docker inspect

获取容器的元数据。
docker_inspect.png

docker exec

在一个运行中的容器中执行命令。

OPTIONS说明:

  • -d: 分离模式: 在后台运行;
  • -i: 即使没有attach 也保持STDIN 打开;
  • -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
docker exec -it 容器id /bin/bash

退出容器

exit   # 容器直接停止并退出
Ctrl + P + Q   #容器不停止退出

docker rename

给容器重命名。

docker rename tomcat9.0.43 tomcat9.0

docker cp

用于容器与宿主机之间拷贝文件。
docker_cp.png

# 将宿主机目录/home/user/data拷贝至容器目录/data/mydata/下
docker cp /home/user/data 96f7f14e99ab:/data/mydata/

# 将宿主机目录/home/user/data拷贝至容器目录中并重命名为/data/mydata
docker cp /home/user/data 96f7f14e99ab:/data/mydata

# 将容器目录/data/mydata拷贝至宿主机目录/tmp下
docker cp 96f7f14e99ab:/data/mydata /tmp/

docker pausedocker unpause

docker pause: 暂停容器中所有进程。
docker unpause: 恢复容器中所有的进程。

docker create

创建一个容器,但不启动容器。方法同docker run

docker commit

从容器中创建一个新的镜像。
OPTIONS说明:

  • -a: 提交镜像的作者(例如:"John Hannibal Smith <hannibal@a-team.com>");
  • -c: 使用Dockerfile指令来创建镜像;
  • -m: 提交的说明信息;
  • -p: 提交镜像时将容器暂停(默认:true)。
# 通过容器创建镜像
docker commit -m="提交的说明信息" -a="作者" 容器id 目标镜像:[TAG]

docker diff

检查容器里文件结构的更改。

Docker镜像

镜像是一种轻量级可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含某个软件所需要的所有内容,包括:运行的代码、库、环境变量、配置文件等。

所有应用直接打包docker镜像,就可以直接运行起来。

Docker获取镜像方式

  • 从远程仓库下载
  • 通过他人拷贝
  • 通过Dockerfile自行制作

UnionFS 联合文件系统

UnionFS (联合文件系统) : Union文件系统(UnionFS) 是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一’ 次提交来一层层的叠加,同时可以将不同月录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

Docker镜像加载原理

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。

bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。

rootfs (root file system) ,在bootfs之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。

img

img

分层的镜像与容器

有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。

    img
    img

  Docker镜像都是只读的,当容器启动时,一个新的可写层镜像加载到镜像顶部!

  这一层就是我们通常说的容器层,容器之下的都叫镜像层。

Docker进阶

容器数据卷

卷技术:容器与宿主机之间可以通过数据卷,实现数据共享,将容器中产生的数据同步到本地。

img

具名和匿名挂载

# 匿名挂载:-v 挂载时,只设置了容器内路径,没有设置容器外路径
# -v 容器内路径(只有容器内路径,没有宿主机路径)
docker run -d -P --name nginx01 -v /etc/nginx nginx

# 查看所有的 volume 信息
root@docker00:~# docker volume ls
DRIVER              VOLUME NAME
local               e3aa274a9c2cbd616657345d4a75bd8c00e0fee28d583a44bb8e0d482321cde7

# 具名挂载: -v 卷名:容器内路径
docker run -d -P --name nginx02 -v named-nginx:/etc/nginx nginx

root@docker00:~# docker volume ls
DRIVER              VOLUME NAME
local               named-nginx

# 查看卷名信息 docker volume inspect
root@docker00:~# docker volume inspect named-nginx
[
    {
        "CreatedAt": "2021-03-17T23:30:47+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/named-nginx/_data",
        "Name": "named-nginx",
        "Options": null,
        "Scope": "local"
    }
]

所有docker容器内的卷,没有指定目录情况下默认都在/var/lib/docker/volumes/xxx/_data

可通过具名挂载可以方便的找到我们的一个卷,大多数情况建议都使用具名挂载

# 区分:具名挂载、匿名挂载、指定路径挂载
-v 卷名:容器内路径   # 具名挂载
-v 容器内路径   # 匿名挂载
-v /宿主机路径:容器内路径   # 指定路径挂载
# 通过 -v 容器内路径:ro rw 改变读写权限
ro   readonly # 只读, 只能通过宿主机来操作,容器内无法操作
rw   readwrite # 可读可写(默认)
docker run -d -P --name nginx02 -v named-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v named-nginx:/etc/nginx:rw nginx

初识DockerFile

Dockerfile 就是用来构建docker镜像的构建文件。

通过这个脚本可以生产镜像,镜像是一层一层的,脚本就是一个个的命令,每个命令就是一层。

# 创建一个dockerfile文件,名称可以自定义,建议使用 Dockerfile

Dockerfile文件内容:

FROM centos

VOLUME ["volume01","volume02"]

CMD echo "---end---"
CMD /bin/bash

image-20210318001030395

image-20210318001352129

查看容器挂载信息:docker container inspect 1444cbf50e22

image-20210318002113841

这种方式使用非常多,因为我们通常会构建自己的镜像。

如果构建镜像时没有挂载卷,需要手动镜像挂载:-v 卷名:容器路径

数据卷容器

--volumes-from:可以实现多个容器间的数据共享。

1、创建父容器mycentos01

image-20210318003657283

2、创建子容器mycentos02

image-20210318004432452

3、进入父容器mycentos01挂载的数据卷创建文件file_from_mycentos01

root@docker00:/home/docker# docker start mycentos01
mycentos01
root@docker00:/home/docker# docker attach mycentos01
[root@645f0a865138 /]# cd volume01
[root@645f0a865138 volume01]# touch file_from_mycentos01
[root@645f0a865138 volume01]# vi file_from_mycentos01
# 设置内容:file_from_mycentos01

4、在子容器mycentos02中查看目录volume01

mycentos01中创建的文件同步至mycentos02

image-20210318005312899

实战:多个mysql共享数据

docker run -d -p 3316:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7

docker run -d -p 3317:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7

# 这样两个容器mysql01和mysql02就可以实现数据同步。

容器间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用该数据卷为止。

数据一旦持久化到本地,本地的数据就不会删除。

DockerFile

DockerFile介绍

Dockerfile 就是用来构建docker镜像的构建文件。

构建步骤:

  1. 编写Dockerfile文件
  2. docker build构建成为一个镜像
  3. docker run运行镜像
  4. docker push发布镜像(DockerHub、阿里云镜像仓库)

image-20210318011654334

image-20210318011807584

背景:很多官方镜像都是基础包,很多功能都没有,我们通常会根据自己的需要搭建自己的镜像。

DockerFile构建过程

基础要求:

  1. 每个指令都必须大写
  2. 执行是从上到下顺序执行
  3. 每个指定都会创建一个新的镜像层,并提交
  4. #表示注释

img

Dockerfile是面向开发的,发布项目时做镜像,就需要编写dockerfile文件。

Dockerfile镜像逐渐成为企业交付的标准,必须熟练掌握。

步骤:

DockerFile:构建文件,定义所有步骤,相当于镜像源代码。

Docker Image镜像:通过DockerFile构建生成的镜像,最终发布和运行的产品。

Docker Container容器:通过镜像运行起来提供的服务。

DockerFile指令

FROM                  # 基础镜像,一切从这里开始
MAINTAINER            # 镜像的作者。 姓名+邮箱
RUN                   # 镜像构建时需要运行的命令
ADD                   # 添加内容。比如制作tomcat镜像,需要添加tomcat压缩包
WORKDIR               # 镜像工作的目录
VOLUME                # 挂载的目录
EXPOSE                # 暴露端口配置
CMD                   # 指定容器启动的时候要运行的命令。只有最后一个会生效,可被替代
ENTRYPOINT            # 指定容器启动的时候要执行的命令,可以追加命令
ONBUILD               # 当构建一个被继承 DockerFile 这个时候就会运行 ONBUILD 指令。触发指令
COPY                  # 类似 ADD ,将我们的文件拷贝到镜像中
ENV                   # 构建的时候设置环境变量    

img

DockerFile实战

创建自己的centos

1、编写Dockerfile文件

FROM centos
LABEL maintainer="xxx@xxx.com"

ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN yum -y install vim
RUN yum -y install net-tools

CMD echo $MYPATH
CMD echo "---end---"

CMD ["/bin/bash"]

2、通过编写好的Dockerfile构建镜像

docker build -f dockerfile_mycentos -t mycentos:0.1 .
# -f 指定需要构建的Dockerfile文件路径
# -t 镜像名:tag

3、根据镜像运行容器

image-20210318021820609

通过docker history获取镜像变更历史:

(我们可以通过查看现有的镜像变更历史,来研究它们是怎么做的)

image-20210318022120568

CMDENTRYPOINT区别

  • CMD:指定这个容器启动的时候要执行的命令,只有最后一个会生效。
  • ENTRYPOINT:指定这个容器启动的时候要运行的命令,可以追加命令。我们追加的命令,是直接拼接在ENTRYPOINT命令后面的。

使用CMD:

Dockerfile内容:

FROM centos
CMD ["ls","-a"]

image-20210318195902515

使用ENTRYPOINT:

Dockerfile内容

FROM centos
ENTRYPOINT ["ls","-a"]

image-20210318200837941

image-20210318200926153

创建自己的Tomcat镜像

1、准备好需要的文件:Tomcat、JDK或JRE压缩包

image-20210318202823718

2、编写Dockerfile文件。官方命名Dockerfile,build会自动寻找这个文件,就不需要通过-f指定dockerfile文件。

FROM centos
LABEL maintainer="xxx<xxx@xxx.com>"

COPY readme.txt /usr/local/readme.txt

ADD  server-jre-8u181-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.44.tar.gz /usr/local/

RUN yum -y install vim

ENV MYPATH /usr/local
WORKDIR $MYPATH

ENV JAVA_HOME /usr/local/jdk1.8.0_181
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HONE/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.44
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.44
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin

EXPOSE 8080

CMD /usr/local/apache-tomcat-9.0.44/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.44/bin/logs/catalina.out

3、构建镜像

docker build -t mytomcat:0.1 .

image-20210318211228143

4、启动镜像

docker run -d -p 18888:8080 -v /home/docker/data/test:/usr/local/apache-tomcat-9.0.44/webapps/test -v /home/docker/data/tomcatlog:/usr/local/apache-tomcat-9.0.44/logs --name mytomcat01 mytomcat:0.1

5、访问

image-20210318213251549

发布自己的镜像

发布镜像至DockerHub

1、需要有自己的账号

2、通过docker login命令登录

image-20210318225351531

3、使用docker push发布镜像

提交的时候是按镜像层级进行提交的。

docker tag local-image:tagname new-repo:tagname
docker push new-repo:tagname

image-20210318230703916

发布镜像至阿里云镜像服务

1、登录阿里云账号进入镜像服务

image-20210318231550025

2、创建命名空间

image-20210318232048268

3、创建镜像仓库

image-20210318231859748

image-20210318232012088

image-20210318232113841

4、获取仓库信息

image-20210318232421986

5、通过docker login登录

image-20210318232953907

6、使用docker push发布镜像

image-20210318233719660

Dockerfile小结

Figure0

Docker网络

docker0网络

通过命令docker network查看docker网络相关信息。

root@docker00:/home/docker# docker network --help

Usage:    docker network COMMAND

Manage networks

Commands:
  connect     Connect a container to a network
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
  ls          List networks
  prune       Remove all unused networks
  rm          Remove one or more networks

Run 'docker network COMMAND --help' for more information on a command.
root@docker00:/home/docker# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
804cd60f60ac        bridge              bridge              local
e9112dc56247        host                host                local
9212c1c4c5f7        none                null                local

image-20210319000044013

启动一个容器:

root@docker00:/home/docker# docker run -d -P --name tomcat01 tomcat

# 查看容器内网络地址 ip addr
# 可以看到容器启动的时候会得到一个 eth0@if19 ip地址。 这个是docker分配的
root@docker00:/home/docker# docker exec -it tomcat01 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    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
18: eth0@if19: <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

# 通过宿主机可以ping同docker容器
root@docker00:/home/docker# ping -c 4 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.186 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.080 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.112 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.208 ms

--- 172.17.0.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3022ms
rtt min/avg/max/mdev = 0.080/0.146/0.208/0.053 ms

image-20210319002038308

再启动一个容器:又多了一对网卡。

image-20210319002947765

查看docker0网卡信息docker network inspect 804cd60f60ac

image-20210319010306580

原理说明
  1. 只要安装了docker,就会有一个网卡docker0,桥接模式;
  2. 每启动一个docker容器,docker就会给容器分配一个ip;
  3. 每启动一个docker容器,docker带来的网卡都是成对的,使用的技术是evth-pair技术;
  4. 多个docker容器是公用一个路由器,即docker0
  5. 所有容器如果不指定网络的情况下,都是docker0路由的,docker会给我们的容器分配一个默认的可用IP
  6. docker中所有的网络接口都是虚拟的。虚拟的网络接口转发效率高。

network.png

evth-pair技术

evth-pair就是一对虚拟设备接口,它们都是成对出现的,一端连着协议,另一端彼此相连。

我们可以利用这个特性,使evth-pair充当一个桥梁,连接各种虚拟网络设备的。

--link

问题:我们的一个服务连接数据库,如果做到项目不重启,更改掉数据库。

解决方法:我们可以通过名称进行访问。

root@docker00:/home/docker# docker run -d -P --name tomcat03 --link tomcat02 tomcat
017be3dbf8a6f94c48cb58afa704dde9900a676eae343cc670ddc3e2d996a557
root@docker00:/home/docker# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.194 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.094 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=3 ttl=64 time=0.140 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=4 ttl=64 time=0.207 ms


root@docker00:/home/docker# docker exec -it tomcat03 cat /etc/hosts
127.0.0.1    localhost
::1    localhost ip6-localhost ip6-loopback
fe00::0    ip6-localnet
ff00::0    ip6-mcastprefix
ff02::1    ip6-allnodes
ff02::2    ip6-allrouters
172.17.0.3    tomcat02 8666f2a63042
172.17.0.4    017be3dbf8a6

--link本质:在hosts配置中增加一条记录,比如上面的172.17.0.3 tomcat02 8666f2a63042

注意:--link现在不建议使用。

docker0的问题:不支持容器名访问。

自定义网络

网络模式:

  1. bridge:桥接模式(默认,我们自定义网络也适用bridge模式)
  2. none:不配置网络
  3. host:和宿主机共享网络
  4. container:容器网络连通(用得少,局限比较多)
# 直接启动容器的命令 --net bridge, 这个bridge就是docker0网络
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat01 --net bridge tomcat

# docker0的特点:默认不能通过域名访问, --link可以打通链接。

docker 网络相关命令:docker networkdocker network create

image-20210319012017286

定义自己的网络:

docker network create --driver bridge --subnet 192.168.6.0/24 --gateway 192.168.6.1 mynet

# --driver bridge   定义网络模式
# --subnet 192.168.6.0/24 子网
# --gateway 192.168.6.1 网关
root@docker00:/home/docker# docker network create --driver bridge --subnet 192.168.6.0/24 --gateway 192.168.6.1 mynet
3c9fe291cfbe918693055e85551a3a1b1e5894cdf3c1742f873e3d2f9c7de232
root@docker00:/home/docker# docker run -d -P --name tomcat01 --net mynet tomcat
ac83ca2e3a007e49d3a76eee4e51357ff54f7a320bb4d595094f459de08e75f1
root@docker00:/home/docker# docker run -d -P --name tomcat02 --net mynet tomcat
0f7a6d2165bdb488ae58ef6cf42d35fd42bc5afbd88adaa29f5b70033c7a1d0a
root@docker00:/home/docker# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
804cd60f60ac        bridge              bridge              local
e9112dc56247        host                host                local
3c9fe291cfbe        mynet               bridge              local
9212c1c4c5f7        none                null                local

root@docker00:/home/docker# docker exec -it tomcat01 ping -c 4 tomcat02
PING tomcat02 (192.168.6.3) 56(84) bytes of data.
64 bytes from tomcat02.mynet (192.168.6.3): icmp_seq=1 ttl=64 time=0.125 ms
64 bytes from tomcat02.mynet (192.168.6.3): icmp_seq=2 ttl=64 time=0.161 ms
64 bytes from tomcat02.mynet (192.168.6.3): icmp_seq=3 ttl=64 time=0.096 ms
64 bytes from tomcat02.mynet (192.168.6.3): icmp_seq=4 ttl=64 time=0.107 ms

--- tomcat02 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 40ms
rtt min/avg/max/mdev = 0.096/0.122/0.161/0.025 ms
root@docker00:/home/docker# docker exec -it tomcat02 ping -c 4 tomcat01
PING tomcat01 (192.168.6.2) 56(84) bytes of data.
64 bytes from tomcat01.mynet (192.168.6.2): icmp_seq=1 ttl=64 time=0.039 ms
64 bytes from tomcat01.mynet (192.168.6.2): icmp_seq=2 ttl=64 time=0.150 ms
64 bytes from tomcat01.mynet (192.168.6.2): icmp_seq=3 ttl=64 time=0.145 ms
64 bytes from tomcat01.mynet (192.168.6.2): icmp_seq=4 ttl=64 time=0.153 ms

--- tomcat01 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 36ms
rtt min/avg/max/mdev = 0.039/0.121/0.153/0.049 ms

image-20210319012832542

image-20210319013841189

image-20210319014020931

我们自定义网络docker都已经帮我们维护好了对应关系,推荐使用我们自定义的网络。

优点:

可以使不同的应用使用不同的网络。

比如:

Redis/MySQL:不同的集群使用不同的网络,保障集群是安全、健康的。

网络连通

docker network connect

root@docker00:/home/docker# docker network connect --help

Usage:    docker network connect [OPTIONS] NETWORK CONTAINER

Connect a container to a network

Options:
      --alias strings           Add network-scoped alias for the container
      --driver-opt strings      driver options for the network
      --ip string               IPv4 address (e.g., 172.30.100.104)
      --ip6 string              IPv6 address (e.g., 2001:db8::33)
      --link list               Add link to another container
      --link-local-ip strings   Add a link-local address for the container
# 创建2个使用默认 bridge 网络的 tomcat 容器
root@docker00:/home/docker# docker run -d -P --name tomcat01bridge tomcat
65c996904744eee0e1f9f47ddd15dc76805c9d363c45ece4a9e245d8b5449db3
root@docker00:/home/docker# docker run -d -P --name tomcat02bridge tomcat
a7336a1a8dc3f4120d7b61051c3a082f911d31865f5e5447a363a4483cd2c66e

# 将容器 tomcat01bridge 连通到网络 mynet
root@docker00:/home/docker# docker network connect mynet tomcat01bridge

# 在容器 tomcat01 中 ping tomcat01bridge
root@docker00:/home/docker# docker exec -it tomcat01 ping -c4 tomcat01bridge
PING tomcat01bridge (192.168.6.4) 56(84) bytes of data.
64 bytes from tomcat01bridge.mynet (192.168.6.4): icmp_seq=1 ttl=64 time=0.163 ms
64 bytes from tomcat01bridge.mynet (192.168.6.4): icmp_seq=2 ttl=64 time=0.108 ms
64 bytes from tomcat01bridge.mynet (192.168.6.4): icmp_seq=3 ttl=64 time=0.146 ms
64 bytes from tomcat01bridge.mynet (192.168.6.4): icmp_seq=4 ttl=64 time=0.107 ms

# 在容器 tomcat01bridge 中 ping tomcat01
root@docker00:/home/docker# docker exec -it tomcat01bridge ping -c 4 tomcat01
PING tomcat01 (192.168.6.2) 56(84) bytes of data.
64 bytes from tomcat01.mynet (192.168.6.2): icmp_seq=1 ttl=64 time=0.109 ms
64 bytes from tomcat01.mynet (192.168.6.2): icmp_seq=2 ttl=64 time=0.155 ms
64 bytes from tomcat01.mynet (192.168.6.2): icmp_seq=3 ttl=64 time=0.109 ms
64 bytes from tomcat01.mynet (192.168.6.2): icmp_seq=4 ttl=64 time=0.129 ms

# 再次查看mynet的信息
root@docker00:/home/docker# docker network inspect mynet

image-20210319015732109

小技巧:要跨网络操作别人的容器,就需要使用docker network connect来进行连通。

Docker实战

实战创建Redis集群

创建网卡:

docker network create redis --driver bridge --subnet 172.68.0.0/16

# 创建网卡
root@docker00:~# docker network create redis --driver bridge --subnet 172.68.0.0/16
d7a4cf0688143f703cf4f9426da8f93404fdc7697fbff576952dc5dc055fabcf

# 创建Redis配置(通过脚步创建6个)
for port in $(seq 1 6); \
do \
mkdir -p /data/redis/node-${port}/conf
touch /data/redis/node-${port}/conf/redis.conf
cat << EOF >/data/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.68.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done

image-20210323202212288

image-20210323203043283

# 创建Redis容器,一共有6个。
root@docker00:/data/redis# docker run -p 6371:6379 -p 16371:16379 --name redis-1 -v /data/redis/node-1/data:/data -v /data/redis/node-1/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.68.0.11 redis:5.0.12-alpine3.13 redis-server /etc/redis/redis.conf

root@docker00:/data/redis# docker run -p 6372:6379 -p 16372:16379 --name redis-2 -v /data/redis/node-2/data:/data -v /data/redis/node-2/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.68.0.12 redis:5.0.12-alpine3.13 redis-server /etc/redis/redis.conf

root@docker00:/data/redis# docker run -p 6373:6379 -p 16373:16379 --name redis-3 -v /data/redis/node-3/data:/data -v /data/redis/node-3/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.68.0.13 redis:5.0.12-alpine3.13 redis-server /etc/redis/redis.conf

root@docker00:/data/redis# docker run -p 6374:6379 -p 16374:16379 --name redis-4 -v /data/redis/node-4/data:/data -v /data/redis/node-4/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.68.0.14 redis:5.0.12-alpine3.13 redis-server /etc/redis/redis.conf

root@docker00:/data/redis# docker run -p 6375:6379 -p 16375:16379 --name redis-5 -v /data/redis/node-5/data:/data -v /data/redis/node-5/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.68.0.15 redis:5.0.12-alpine3.13 redis-server /etc/redis/redis.conf

root@docker00:/data/redis# docker run -p 6376:6379 -p 16376:16379 --name redis-6 -v /data/redis/node-6/data:/data -v /data/redis/node-6/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.68.0.16 redis:5.0.12-alpine3.13 redis-server /etc/redis/redis.conf
# 创建集群
/data # redis-cli --cluster create 172.68.0.11:6379 172.68.0.12:6379 172.68.0.13:6379 172.68.0.14:6379 172.68.0.15:6379 172.68.0.16
:6379 --cluster-replicas 1
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.68.0.15:6379 to 172.68.0.11:6379
Adding replica 172.68.0.16:6379 to 172.68.0.12:6379
Adding replica 172.68.0.14:6379 to 172.68.0.13:6379
M: a56213ba8e6512f47e9b113242cbd26a04c9b1c4 172.68.0.11:6379
   slots:[0-5460] (5461 slots) master
M: 9970c171e1d4d3b14d01d64f008e98287edfd6e3 172.68.0.12:6379
   slots:[5461-10922] (5462 slots) master
M: 8041851b334790ee99be68e525252a80a0ca6c1d 172.68.0.13:6379
   slots:[10923-16383] (5461 slots) master
S: f9eca8ade53518d881abe06a7702960989b0670a 172.68.0.14:6379
   replicates 8041851b334790ee99be68e525252a80a0ca6c1d
S: 374d5e6755744ceee4c2d6c3c33fa7e01ff968f9 172.68.0.15:6379
   replicates a56213ba8e6512f47e9b113242cbd26a04c9b1c4
S: 11adc56af02e65684b5353096cd396de354f5eba 172.68.0.16:6379
   replicates 9970c171e1d4d3b14d01d64f008e98287edfd6e3
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
...
>>> Performing Cluster Check (using node 172.68.0.11:6379)
M: a56213ba8e6512f47e9b113242cbd26a04c9b1c4 172.68.0.11:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: f9eca8ade53518d881abe06a7702960989b0670a 172.68.0.14:6379
   slots: (0 slots) slave
   replicates 8041851b334790ee99be68e525252a80a0ca6c1d
S: 11adc56af02e65684b5353096cd396de354f5eba 172.68.0.16:6379
   slots: (0 slots) slave
   replicates 9970c171e1d4d3b14d01d64f008e98287edfd6e3
M: 9970c171e1d4d3b14d01d64f008e98287edfd6e3 172.68.0.12:6379
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
M: 8041851b334790ee99be68e525252a80a0ca6c1d 172.68.0.13:6379
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: 374d5e6755744ceee4c2d6c3c33fa7e01ff968f9 172.68.0.15:6379
   slots: (0 slots) slave
   replicates a56213ba8e6512f47e9b113242cbd26a04c9b1c4
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

连接集群:redis-cli -c,查看集群信息cluster info、集群节点cluster nodes

image-20210323205733978

# 集群测试
# 设置值
127.0.0.1:6379> set k1 v1
-> Redirected to slot [12706] located at 172.68.0.13:6379
OK

# 将172.68.0.13对应的容器停止
root@docker00:~# docker stop redis-3

# 获取值
/data # redis-cli -c
127.0.0.1:6379> get k1
-> Redirected to slot [12706] located at 172.68.0.14:6379
"v1"

# 查看集群节点
172.68.0.14:6379> cluster nodes
a56213ba8e6512f47e9b113242cbd26a04c9b1c4 172.68.0.11:6379@16379 master - 0 1616504607000 1 connected 0-5460
374d5e6755744ceee4c2d6c3c33fa7e01ff968f9 172.68.0.15:6379@16379 slave a56213ba8e6512f47e9b113242cbd26a04c9b1c4 0 1616504607000 5 connected
8041851b334790ee99be68e525252a80a0ca6c1d 172.68.0.13:6379@16379 master,fail - 1616504393932 1616504392000 3 connected
11adc56af02e65684b5353096cd396de354f5eba 172.68.0.16:6379@16379 slave 9970c171e1d4d3b14d01d64f008e98287edfd6e3 0 1616504608745 6 connected
9970c171e1d4d3b14d01d64f008e98287edfd6e3 172.68.0.12:6379@16379 master - 0 1616504607730 2 connected 5461-10922
f9eca8ade53518d881abe06a7702960989b0670a 172.68.0.14:6379@16379 myself,master - 0 1616504608000 7 connected 10923-16383

SpringBoot打包Docker镜像

步骤:

  1. 开发项目
  2. 打包应用
  3. 编写Dockerfile
  4. 构建镜像
  5. 运行
编写Dockerfile
FROM java:8

COPY *.jar /app.jar

CMD ["--server.port=8080"]

EXPOSE 8080

ENTRYPOINT ["java","-jar","/app.jar"]
构建镜像
# 查看工作目录文件
root@docker00:/data/docker/springboot# ll
total 19884
-rw-r--r-- 1 root root      112 Mar 23 21:31 Dockerfile
-rw-r--r-- 1 root root 20357002 Mar 23 21:31 springboot-demo-1.0-SNAPSHOT.jar

# 打包镜像
root@docker00:/data/docker/springboot# docker build -t demospringboot:1.0 .
Sending build context to Docker daemon  20.36MB
Step 1/5 : FROM java:8
8: Pulling from library/java
5040bd298390: Pull complete
fce5728aad85: Pull complete
76610ec20bf5: Pull complete
60170fec2151: Pull complete
e98f73de8f0d: Pull complete
11f7af24ed9c: Pull complete
49e2d6393f32: Pull complete
bb9cdec9c7f3: Pull complete
Digest: sha256:c1ff613e8ba25833d2e1940da0940c3824f03f802c449f3d1815a66b7f8c0e9d
Status: Downloaded newer image for java:8
 ---> d23bdf5b1b1b
Step 2/5 : COPY *.jar /app.jar
 ---> bd52eb60c058
Step 3/5 : CMD ["--server.port=8080"]
 ---> Running in 6dd1c6b0d94a
Removing intermediate container 6dd1c6b0d94a
 ---> 9d61c697466a
Step 4/5 : EXPOSE 8080
 ---> Running in 6e7460e821a5
Removing intermediate container 6e7460e821a5
 ---> ddf374755516
Step 5/5 : ENTRYPOINT ["java","-jar","/app.jar"]
 ---> Running in 392e27aeefb4
Removing intermediate container 392e27aeefb4
 ---> e8ce8b7283a7
Successfully built e8ce8b7283a7
Successfully tagged demospringboot:1.0

image-20210323213742375

运行测试
root@docker00:/data/docker/springboot# docker run -d -P --name demospringboot01 demospringboot:1.0
f88f4029e199c212483f79f40ed023eb079c1b1e9c7c089f351c57dd3fed1fec

root@docker00:/data/docker/springboot# docker ps
CONTAINER ID        IMAGE                COMMAND                  CREATED             STATUS              PORTS                     NAMES
f88f4029e199        demospringboot:1.0   "java -jar /app.jar …"   25 seconds ago      Up 24 seconds       0.0.0.0:32768->8080/tcp   demospringboot01
root@docker00:/data/docker/springboot#

# 测试
root@docker00:/data/docker/springboot# curl http://localhost:32768
index >>> Welcome To SpringBoot!

image-20210323214150049

标签: docker

添加新评论