docker学习笔记--狂神

2023-11-13

Docker入门

Docker能做什么

虚拟机技术:

虚拟机技术

虚拟机技术缺点:

  1. 资源占用十分多
  2. 冗余步骤多
  3. 启动很慢

容器化技术

容器化技术不是模拟的一个完整的操作系统。

docker

比较Docker 和 虚拟机技术不用:

  • 传统虚拟机,虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
  • 容器内的应用直接运行在 宿主机的内容,容器是没有自己的内核的,也没有虚拟我们的硬件。所以就轻便了。
  • 每个容器间是互相隔离的,每个容器内都有一个属于自己的文件系统,互不影响

DecOps(开发、运维)

  • 应用更快速的交付和部署

    传统:一堆帮助文档,安装程序

    Docker:打包镜像发布测试,一键运行

  • 更便捷的升级和扩缩容

    使用Docker之后,我们部署应用就和搭积木一样!

    项目打包为一个镜像,(可以理解为一个应用,带着环境能直接跑起来),扩展 服务器A! 直接在服务器B上一键运行即可。

  • 更简单的系统运维

    在容器化之后,我们的开发,测试环境都是高度一致的

  • 更高效的计算资源利用

    Docker 是 内核级别的虚拟化,可以在一个物理机上能运行很多的容器实例!服务器的性能可以被压着到极致!


Docker安装

Docker基本组成

Docker架构图

镜像(image):

​ docker镜像就好比一个模版,可以通过这个模版来创建容器服务,例:tomcat镜像 = == >run ===>tomcat01容器(提供服务),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)

容器(container):

​ Docker利用容器技术,独立运行一个或者一组应用,通过镜像来创建的。
​ 启动、停止、删除,基本命令!
目前就可以把这个容器理解为就是一个简易的linux系统。

仓库(repository):

​ 仓库是存放镜像的地方!
​ 仓库分为共有仓库和私有仓库!
​ Docker Hub(默认是国外的)
​ 阿里云…都有容器服务(配置镜像加速!)

安装Docker

环境查看

#系统内核
root@ecs-7ed1:~# uname -r
4.15.0-136-generic

# 系统版本
root@ecs-7ed1:~# cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.5 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.5 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic

安装

帮助文档:

示例Ubuntu

# 1.卸载旧的版本
 sudo apt-get remove docker docker-engine docker.io containerd runc
 
# 2.安装 apt 依赖包,用于通过HTTPS来获取仓库:
apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg \
    lsb-release
    
# 3.添加Docker官方GPG key
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | apt-key add -  	#(阿里云版本)

# 4.验证key的指纹
sudo apt-key fingerprint 0EBFCD88

# 5.设置稳定版仓库repository
sudo add-apt-repository \
   "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

# 更新apt包索引
sudo apt-get update

# 6.安装最新版的docker ce和containerd		ce是社区版  ee是企业版
sudo apt-get install docker-ce docker-ce-cli containerd.io
#查看文档,可安装指定版本

# 7.查看docker版本
docker --version

# 8.测试hello-world
docker run hello-world

测试hello-world 结果:

1)不能找到hello-world镜像;2)pull拉取;3)拉取完成;4)运行hello-world

测试hello-world

# 查看一下下载的hello-world镜像
root@ecs-7ed1:~# docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
hello-world   latest    d1165f221234   5 months ago   13.3kB

了解:下载docker

# 1.卸载依赖
sudo apt-get purge docker-ce docker-ce-cli containerd.io
# 2.删除镜像
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd

#  /var/lib/docker   docker的默认工作路径

回顾hello-world流程

run的运行流程图

底层原理

Docker是怎么工作的?

Docker是一个Client - Server 结构的系统,Docker的守护进程运行在主机上,通过Socket从客户端访问!

Docker-Server接收到Docker-Client的指令,就会执行这个命令!

image-20210820145709336

Docker为什么比虚拟机VM快?

  1. Docker有着比虚拟机更少的抽象层。

    Hypervisor(虚拟机监视器),是运行在物理服务器和操作系统之间的中间软件层,可允许多个操作系统和应用共享一套基础物理硬件。

  2. docker利用的是宿主机的内核,vm需要是Guest OS。

所以说,新建一个容器的时候,docker不需要像虚拟机一样重新加载一个操作系统内核,避免引导。虚拟机是加载Guest OS,是分钟级别的,而==docker是利用宿主机的操作系统==,省略了这个复杂的过程,秒级!

image-20210820151437072

现在GuestOS 支持所有系统

Docker的常用命令

帮助命令

docker version		#显示docker的版本信息
docker info			#显示docker
docker 命令 --help   #

帮助文档地址:https://docs.docker.com/reference/

镜像命令

docker images 查看所有本地的主机上的镜像

root@ecs-7ed1:~# docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
hello-world   latest    d1165f221234   5 months ago   13.3kB

# 解释
REPOSITORY	镜像的仓库源
TAG			镜像的标签
IMAGE ID	镜像的id
CREATED		镜像的创建时间
SIZE		镜像的大小

# 可选项
  -a, --all             # 列出所有的镜像
  -q, --quiet           # 只显示镜像的ID

docker search 搜索镜像

root@ecs-7ed1:~# docker search mysql
NAME                              DESCRIPTION                                     STARS     O             FFICIAL   AUTOMATED
mysql                             MySQL is a widely used, open-source relation…   11299     [             OK]
mariadb                           MariaDB Server is a high performing open sou…   4291      [             OK]

# 可选项,通过收藏来过滤
root@ecs-7ed1:~# docker search mysql --filter=STARS=3000
NAME      DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql     MySQL is a widely used, open-source relation…   11299     [OK]
mariadb   MariaDB Server is a high performing open sou…   4291      [OK]

docker pull 下载镜像

#下载镜像 docker pull 镜像名[:tag]
root@ecs-7ed1:~# docker pull mysql
Using default tag: latest	 #如果不写 tag ,默认就是latest。(最新的,tag是版本号)
latest: Pulling from library/mysql
e1acddbe380c: Pull complete		#分层下载,docker image的核心  联合文件系统
bed879327370: Pull complete
03285f80bafd: Pull complete
ccc17412a00a: Pull complete
1f556ecc09d1: Pull complete
adc5528e468d: Pull complete
1afc286d5d53: Pull complete
6c724a59adff: Pull complete
0f2345f8b0a3: Pull complete
c8461a25b23b: Pull complete
3adb49279bed: Pull complete
77f22cd6c363: Pull complete
Digest: sha256:d45561a65aba6edac77be36e0a53f0c1fba67b951cb728348522b671ad63f926 #签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest		#真实地址

# 下面两个命令等价
docker pull mysql
docker pull docker.io/library/mysql:latest		#通过真实地址pull

#指定版本下载————版本根据docker hub中的所含版本,不能随意填写
root@ecs-7ed1:~# docker pull mysql:5.7
5.7: Pulling from library/mysql
e1acddbe380c: Already exists		#表示已经存在
bed879327370: Already exists
03285f80bafd: Already exists
ccc17412a00a: Already exists
1f556ecc09d1: Already exists
adc5528e468d: Already exists
1afc286d5d53: Already exists
4d2d9261e3ad: Pull complete			#新下载文件
ac609d7b31f8: Pull complete
53ee1339bc3a: Pull complete
b0c0a831a707: Pull complete
Digest: sha256:7cf2e7d7ff876f93c8601406a5aa17484e6623875e64e7acc71432ad8e0a3d7e
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7

docker rmi 删除镜像!

root@ecs-7ed1:~# docker rmi -f 容器id		#删除指定的镜像
root@ecs-7ed1:~# docker rmi -f 容器id 容器id 容器id 容器id	#删除多个指定镜像
root@ecs-7ed1:~# docker rmi -f $(docker images -ap)		#删除全部的镜像

容器命令

说明:我们有了镜像才可以创建容器,linux,下载一个centos镜像来测试学习

docker pull centos

新建容器并启动

docker run [可选参数] image

# 参数说明
--name='Name'	#容器名字 tomcat01  tomcat02 , 用来区分容器
-d 				#后台方式运行
-i
-t				#使用交互方式运行,进入容器查看内容。一般使用  -it
-p				#指定容器的端口	-p  8080:8080
	-p ip:主机端口:容器端口
	-p 主机端口:容器端口 (常用)
	-p 容器端口
	容器端口
-P				随机指定端口


# 测试,启动并进入容器
root@ecs-7ed1:~# docker run -it centos /bin/bash		#shell程序bash??
[root@35ace831db17 /]# ls		#查看容器内的centos,基础版本,很多命令都是不完善的!
bin  etc   lib    lost+found  mnt  proc  run   srv  tmp  var
dev  home  lib64  media       opt  root  sbin  sys  usr

#从容器中退出主机
[root@35ace831db17 /]# exit
exit

root@ecs-7ed1:~# ls
cmake-3.9.2                  GolangStudy  mysql-8.0.24                       TinyWebServer
cmake-3.9.2.tar.gz           gowork       mysql-apt-config_0.8.10-1_all.deb  webserver
go                           hello.go     oasys_mysql
go1.16.7.linux-amd64.tar.gz  maven        oasys_mysql.sql

列出所有的运行容器

#docker ps 命令
  	#列出当前正在运行的容器
-a  #列出当前正在运行的容器+带出历史运行过的容器
-n=?  #显示最近创建的n个容器
-q	 #只显示容器的编号

root@ecs-7ed1:~# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
root@ecs-7ed1:~# docker ps -a
CONTAINER ID   IMAGE         COMMAND       CREATED         STATUS                          PORTS     NAMES
35ace831db17   centos        "/bin/bash"   4 minutes ago   Exited (0) About a minute ago             hardcore_matsumoto
3f161b15937c   hello-world   "/hello"      24 hours ago    Exited (0) 24 hours ago                   quirky_johnson

退出容器

exit	#直接容器停止并退出。。。。。exit应该是终止没有前台程序的容器
Ctrl + P + Q	#容器不停止退出

删除容器

docker rm 容器id			#删除指定容器,不能删除正在运行的容器,如果要强制删除  rm -f 
docker rm -f $(docker ps -aq)	#删除所有容器
docker ps -a -q | xargs	docker rm		#删除所有容器

启动和停止容器的操作

docker start 容器id		#启动容器
docker restart 容器id		#重启容器
docker stop 容器id		#停止当前正在运行的容器
docker kill 容器id		# 强制停止当前容器

常用其他命令

后台启动容器

# 命令 docker run -d 镜像名
root@ecs-7ed1:~# docker run -d centos

#问题 docker ps,发现 centos 停止了

#常见的坑:docker 容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止
#nginx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了

查看日志

docker logs -f -t --tail 容器,没有日志

#自己编写一段shell脚本
root@ecs-7ed1:~# docker run -d centos /bin/sh -c "while true;do echo qiuzhiming;sleep 1;done"

#查看id
root@ecs-7ed1:~# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS     NAMES
fb5718858632   centos    "/bin/sh -c 'while t…"   3 seconds ago   Up 2 seconds             condescending_perlman

#显示日志	
#--tail number 显示的日志条数
#-t 		   时间戳
#-f  		   是跟踪日志输出,相当于实时显示
root@ecs-7ed1:~# docker logs -t -f --tail 10 fb5718858632
2021-08-31T13:01:08.087901329Z qiuzhiming
2021-08-31T13:01:09.089473375Z qiuzhiming
2021-08-31T13:01:10.089974061Z qiuzhiming
2021-08-31T13:01:11.091694770Z qiuzhiming
2021-08-31T13:01:12.093801482Z qiuzhiming
2021-08-31T13:01:13.095234152Z qiuzhiming

查看容器中的进程信息

#docker top 容器id

root@ecs-7ed1:~# docker top fb5718858632
UID                 PID   当前进程id         PPID 父进程id            C                   STIME               TTY                 TIME                CMD
root                16796               16768               0                   20:58               ?                   00:00:00            /bin/sh -c while true;do echo qiuzhiming;sleep 1;done
root                20397               16796               0                   21:51               ?                   00:00:00            /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1

查看镜像的元数据

#docker inspect 容器id

进入当前正在运行的容器

# 我们通常容器都是使用后台方式运行的,需要进入容器,修改一些配置

# 命令-方式一
docker exec -it 容器id bashshell

#测试
root@ecs-7ed1:~# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED        STATUS        PORTS     NAMES
fb5718858632   centos    "/bin/sh -c 'while t…"   12 hours ago   Up 12 hours             condescending_perlman
c9cd446d4fb4   centos    "/bin/bash"              12 hours ago   Up 12 hours             lucid_jennings
root@ecs-7ed1:~# docker exec -it c9cd446d4fb4 /bin/bash
[root@c9cd446d4fb4 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

# 方式二
docker attach 容器id


#docker exec	#进入容器开启一个新的终端,可以在里面操作(常用)
#docker attach	#进入容器正在执行的终端,不会启动新的进程!如果进入的容器没有正在运行脚本,则效果和docker exec相同

#测试,第一次进入的容器后台无运行脚本,第二次进入的容器后台不停的在运行脚本。
root@ecs-7ed1:~# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED        STATUS        PORTS     NAMES
fb5718858632   centos    "/bin/sh -c 'while t…"   12 hours ago   Up 12 hours             condescending_perlman
c9cd446d4fb4   centos    "/bin/bash"              13 hours ago   Up 13 hours             lucid_jennings
root@ecs-7ed1:~# docker attach c9cd446d4fb4
[root@c9cd446d4fb4 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@c9cd446d4fb4 /]# read escape sequence				# 退出容器终端 Ctrl+P+Q
root@ecs-7ed1:~# docker attach fb5718858632
qiuzhiming
qiuzhiming
qiuzhiming
...

从容器内拷贝文件到主机上

docker cp 容器id:容器内路径  目的主机路径

#测试。只要容器在,数据就在,和它正在运行与否无关

root@ecs-7ed1:~# docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED        STATUS        PORTS     NAMES
c9cd446d4fb4   centos    "/bin/bash"   13 hours ago   Up 13 hours             lucid_jennings
root@ecs-7ed1:~# docker attach c9cd446d4fb4
[root@c9cd446d4fb4 home]# ls
[root@c9cd446d4fb4 home]# touch test.cpp
[root@c9cd446d4fb4 home]# ls
test.cpp
[root@c9cd446d4fb4 home]# exit
exit

root@ecs-7ed1:~# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
root@ecs-7ed1:~# docker ps -a
CONTAINER ID   IMAGE         COMMAND                  CREATED        STATUS                        PORTS     NAMES
c9cd446d4fb4   centos        "/bin/bash"              13 hours ago   Exited (0) 12 seconds ago               lucid_jennings

root@ecs-7ed1:~# pwd
/root
root@ecs-7ed1:~# ls
root@ecs-7ed1:~# docker cp c9cd446d4fb4:/home/test.cpp /root
root@ecs-7ed1:~# ls
test.cpp

# 拷贝是一个手动过程,未来我们使用 -v 卷的技术,可以实现自动同步

小节

root@ecs-7ed1:~# docker --help

  attach      Attach local standard input, output, and error streams to a running container	#当前shell下 attach 连接指定运行镜像
  build       Build an image from a Dockerfile						#通过 Dockrfile 定制镜像
  commit      Create a new image from a container's changes			#提交当前容器为新的镜像
  cp          Copy files/folders between a container and the local filesystem	#从容器中拷贝指定文件或者目录到宿主机中
  create      Create a new container	#创建一个新的容器,同run,但不启动容器
  diff        Inspect changes to files or directories on a container's filesystem	#查看 docker 容器变化
  events      Get real time events from the server	#从 docker 服务获取容器实时事件
  exec        Run a command in a running container	# 在已存在的容器上运行命令
  export      Export a container's filesystem as a tar archive	# 导出容器的内容流作为一个tar归档文件[对应 import ]
  history     Show the history of an image	# 展示一个镜像形成历史
  images      List images	# 列出系统当前镜像
  import      Import the contents from a tarball to create a filesystem image # 从tar包中的内容创建一个新的文件系统映像[对应export]
  info        Display system-wide information	# 显示系统相关信息
  inspect     Return low-level information on Docker objects	# 查看容器详细信息
  kill        Kill one or more running containers	# kill指定容器
  load        Load an image from a tar archive or STDIN	# 从一个tar包中加载一个镜像
  login       Log in to a Docker registry	# 注册或者登陆一个 docker 源服务器
  logout      Log out from a Docker registry	# 从当前 docker registry 退出
  logs        Fetch the logs of a container	# 输出当前容器日志信息
  pause       Pause all processes within one or more containers	# 暂停服务器
  port        List port mappings or a specific mapping for the container	# 查看映射端口对应的容器内部源端口
  ps          List containers	# 列出容器列表
  pull        Pull an image or a repository from a registry	# 从镜像源服务器拉取指定镜像或者库镜像
  push        Push an image or a repository to a registry	# 推送指定镜像或者库镜像至docker源服务器
  rename      Rename a container	# 重命名容器
  restart     Restart one or more containers # 重启运行的容器
  rm          Remove one or more containers	# 移除一个或者多个容器
  rmi         Remove one or more images	# 移除一个或者多个镜像[无容器使用该镜像才可删除,否则需删除相关容器才可继续或 -f 强制删除]
  run         Run a command in a new container	# 创建一个新的容器并运行一个命令
  save        Save one or more images to a tar archive (streamed to STDOUT by default)	# 保存一个镜像为一个 tar包[对应load]
  search      Search the Docker Hub for images	#在docker hub中搜索镜像
  start       Start one or more stopped containers # 启动容器
  stats       Display a live stream of container(s) resource usage statistics # 显示容器资源使用信息
  stop        Stop one or more running containers #停止容器
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE	# 给源中镜像打标签
  top         Display the running processes of a container	# 查看容器中运行的进程信息
  unpause     Unpause all processes within one or more containers	# 取消暂停容器
  update      Update configuration of one or more containers	#更新容器配置
  version     Show the Docker version information	# 查看docker版本号
  wait        Block until one or more containers stop, then print their exit codes	# 截取容器停止时的退出状态值

作业练习

部署nginx
# 搜索镜像 search	,建议去官网docker hub上搜索,可以查看详细信息

# 下载镜像 pull
root@ecs-7ed1:~# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
e1acddbe380c: Already exists
e21006f71c6f: Pull complete
f3341cc17e58: Pull complete
2a53fa598ee2: Pull complete
12455f71a9b5: Pull complete
b86f2ba62d17: Pull complete
Digest: sha256:4d4d96ac750af48c6a551d757c1cbfc071692309b491b70b2b8976e102dd3fef
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest

# 查看镜像
root@ecs-7ed1:~# docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
nginx         latest    dd34e67e3371   2 weeks ago    133MB
mysql         latest    5a4e492065c7   2 weeks ago    514MB
hello-world   latest    d1165f221234   5 months ago   13.3kB
centos        latest    300e315adb2f   8 months ago   209MB

# 运行镜像  -d后台运行,--name 命名, -p 暴露端口号,3344:80(宿主机端口:容器内部端口)打通宿主机与容器
root@ecs-7ed1:~# docker run -d --name nginx01 -p 3344:80 nginx
809eebe3695a2a14a84f37a6111da4c40dfeed135f3b4a04b976a2f63148dbea
#查看运行的容器
root@ecs-7ed1:~# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                                   NAMES
809eebe3695a   nginx     "/docker-entrypoint.…"   4 seconds ago   Up 4 seconds   0.0.0.0:3344->80/tcp, :::3344->80/tcp   nginx01

#测试,使用3344可以访问成功
root@ecs-7ed1:~# curl localhost:3344
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

端口暴露

外部公网可以访问

image-20210901113211640

root@ecs-7ed1:~# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                   NAMES
809eebe3695a   nginx     "/docker-entrypoint.…"   14 minutes ago   Up 14 minutes   0.0.0.0:3344->80/tcp, :::3344->80/tcp   nginx01

# 进入容器
root@ecs-7ed1:~# docker exec -it nginx01 /bin/bash

# 查一下nginx在哪
root@809eebe3695a:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx

# 进入目录
root@809eebe3695a:/# cd /etc/nginx
root@809eebe3695a:/etc/nginx# ls
conf.d  fastcgi_params  mime.types  modules  nginx.conf  scgi_params  uwsgi_params

# 退出
root@809eebe3695a:/etc/nginx# exit
exit
root@ecs-7ed1:~# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                   NAMES
809eebe3695a   nginx     "/docker-entrypoint.…"   16 minutes ago   Up 16 minutes   0.0.0.0:3344->80/tcp, :::3344->80/tcp   nginx01

# 停止
root@ecs-7ed1:~# docker stop 809eebe3695a
809eebe3695a
root@ecs-7ed1:~# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

思考:每次改动nginx配置文件,都需要进入容器内部,十分麻烦,要是可以在容器外部提供一个映射路径,达到在容器修改文件名,容器内部就可以自动修改?-v 数据卷技术!

部署tomcat
# 下载镜像
docker pull tomcat

# 运行镜像
docker run -d -p 3344:8080 --name tomcat01 tomcat

#此时用 IP:3344 测试访问成功但是无内容显示。而且缺少部分linux命令
# 这是阿里云镜像的原因:默认使用最小镜像,所有不必要的都剔除了,保证最小可运行环境

#进入容器,查看webapps中无内容
root@ecs-7ed1:~# docker exec -it tomcat01 /bin/bash
root@8456cf6ee5f9:/usr/local/tomcat# ls
BUILDING.txt  CONTRIBUTING.md  LICENSE  NOTICE  README.md  RELEASE-NOTES  RUNNING.txt  bin  conf  lib  logs  native-jni-lib  temp  webapps  webapps.dist  work
root@8456cf6ee5f9:/usr/local/tomcat# cd webapps
root@8456cf6ee5f9:/usr/local/tomcat/webapps# ls

# copy webcpps.dist的内容到webcpps
root@8456cf6ee5f9:/usr/local/tomcat/webapps# cd ..
root@8456cf6ee5f9:/usr/local/tomcat# ls
BUILDING.txt  CONTRIBUTING.md  LICENSE  NOTICE  README.md  RELEASE-NOTES  RUNNING.txt  bin  conf  lib  logs  native-jni-lib  temp  webapps  webapps.dist  work
root@8456cf6ee5f9:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@8456cf6ee5f9:/usr/local/tomcat# cd webapps
root@8456cf6ee5f9:/usr/local/tomcat/webapps# ls
ROOT  docs  examples  host-manager  manager

#测试运行成功

第一次测试

第二次测试

**思考问题:**我们以后部署项目,如果每次都要进入容器是不是身份麻烦?我要是可以在容器外部提供一个映射路径,webapps,我们在外部放置项目,就自动同步到内部就好了!

docker容器 tomcat+网站

docker mysql

部署es+kibana
# es 暴露的端口很多
# es 十分耗内存
# es 的数据一般需要放置到安全目录!挂载
# --net somenetwork ?   网络配置

# 下载启动
docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2

# 启动之后  linux就卡住了   因为es很耗内存
root@ecs-7ed1:~# curl localhost:9200
{
  "name" : "77a654314216",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "tc3RpVT6Q0iOkPei6Fd4vg",
  "version" : {
    "number" : "7.6.2",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
    "build_date" : "2020-03-26T06:34:37.794943Z",
    "build_snapshot" : false,
    "lucene_version" : "8.4.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

# docker stats	查看cpu状态
root@ecs-7ed1:~# docker stats 77a654314216
CONTAINER ID   NAME            CPU %     MEM USAGE / LIMIT     MEM %     NET I/O         BLOCK I/O        PIDS
77a654314216   elasticsearch   0.00%     1.253GiB / 3.852GiB   32.54%    1.47kB / 984B   11.4MB / 729kB   44


# 关闭,然后通过 -e 限制内存。	修改配置文件 -e 环境配置修改
docker run -d --name elasticsearch01 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2

# 测试通过
root@ecs-7ed1:~# curl localhost:9200
{
  "name" : "47837f868e13",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "ggOY5REmSoeXvwfVA_Eh4A",
  "version" : {
    "number" : "7.6.2",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
    "build_date" : "2020-03-26T06:34:37.794943Z",
    "build_snapshot" : false,
    "lucene_version" : "8.4.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

# 查看占用内存。  显著下降
root@ecs-7ed1:~# docker stats 47837f868e13
CONTAINER ID   NAME              CPU %     MEM USAGE / LIMIT     MEM %     NET I/O          BLOCK I/O        PIDS
47837f868e13   elasticsearch01   0.00%     351.1MiB / 3.852GiB   8.90%     2.24kB / 1.4kB   2.97MB / 729kB   44

思考:用kibana链接elasticsearch

可视化

  • portainer (先用这个)
  • Rancher (CI/CD时用) 持续集成和持续部署
portainer

Docker图像化界面管理工具,提供一个后台面板供我们操作!

# 启动
root@ecs-7ed1:~# docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

外网访问

image-20210902110559671

本地连接

image-20210902110731476

image-20210902110359153

Docker镜像

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

如何获得镜像:

  • 从远程仓库下载
  • 朋友拷贝
  • 自己制作一个镜像 DockerFile

原理

UnionFS 联合文件系统

bootfs:boot file system 启动内核kernel,不同系统基本一致

rootfs:root file system **不同系统的主要差别。**包含典型linux系统中的/dev , /proc , /bin , /etc 等标准目录和文件。只需包含基本命令,工具和程序库

分层理解

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

上图是每个镜像大的分层

下图将镜像的每层细分为多个文件

下图示意迭代更新文件5的原理

若pull新的镜像的分层,与原主机上的镜像分层的文件相同,则不需重新下载,可直接使用已下载镜像的层。(环境复用)

下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供同一的视图。

image-20210902144734461

Docker镜像都是只读的,当容器启动时,一个新的可写层被加到镜像的顶部,这一层就是我们通常说的容器层,容器层之下的都叫镜像层

commit提交镜像

docker commit # 提交容器成为一个新的副本

# 命令与git原理基本一致
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]

实战测试

# 运行tomcat
root@ecs-7ed1:~# docker run -d -p 8080:8080 tomcat

# 将webapps.dist里面所有的文件拷贝到webapps里面,其中-r必须有,表示目录递归拷贝 (已在部署tomcat部分操作)

# 提交镜像到本地
root@ecs-7ed1:~# docker commit -m="add webapps app" -a="sunwukong" fa14a6266117 tomcat02:1.0

查看提交结果:

image-20210902150436790

测试在新的镜像tomcat02上创建容器

# 创建容器,失败。pull tomcat02失败,并没有直接运行本地的镜像
root@ecs-7ed1:~# docker run -d -p 3344:8080 tomcat02
Unable to find image 'tomcat02:latest' locally
docker: Error response from daemon: pull access denied for tomcat02, repository does not exist or may require 'docker login': denied: requested access to the resource is denied.
See 'docker run --help'.

# 在镜像名后加TAG,运行成功
root@ecs-7ed1:~# docker run -d -p 3344:8080 tomcat02:1.0
6d468dc745c72777f38af8432180a5f95e049d7a095c7103fba3dbcb4bf45b01

# 改用镜像id运行,成功
root@ecs-7ed1:~# docker run -d -p 3344:8080 f6a582ac8a28
15e4e09d9faa40ca2b3ae20fa35e1babe961a4169294723f9ec827a13d25647b
root@ecs-7ed1:~# docker ps
CONTAINER ID   IMAGE          COMMAND             CREATED         STATUS         PORTS                                       NAMES
15e4e09d9faa   f6a582ac8a28   "catalina.sh run"   5 seconds ago   Up 4 seconds   0.0.0.0:3344->8080/tcp, :::3344->8080/tcp   pedantic_allen

# 外网访问成功

容器数据卷

什么是容器数据卷

docker是要将应用和环境打包成一个镜像

这样,数据就不应该在容器中,否则容器删除,数据就会丢失,这就是删库跑路

故容器之间要有一个数据共享技术

在Docker容器中产生的数据,同步到本地,这就是卷技术

本质上是一个==目录挂载==,将容器内的目录挂载到虚拟机上

**挂载:**指的就是将设备文件中的顶级目录连接到 Linux 根目录下的某一目录(最好是空目录),访问此目录就等同于访问设备文件。

参考:挂载讲解

目的:容器的持久化和同步操作

容器间可以数据共享

数据卷是被设计用来持久化数据的,它的生命周期独立于容器,Docker不会在容器被删除后自动删除数据卷。如果需要在删除容器的同时移除数据卷,可以在删除容器的时候使用 docker rm -v 这个参数。

使用数据卷

docker run -it -v -p
# -it 交互式进入
# -v volume卷技术
# -p 主机端口

# 测试
docker run -it -v /home/ceshi:/home/ centos /bin/bash

# docker inspect 容器id	,找到挂载信息Mounts

测试

容器停止后,修改主机文件,再启动容器的时候,数据同样改变

双向同步

好处:我们以后修改只需要在本地修改即可,容器内会自动同步!

假设我们将容器删除,发现,我们挂载到本地的数据卷依旧没有丢失,这就是先了容器数据持久化功能!

具名挂载和匿名挂载

# 匿名挂载    
# -v 容器内路径!
 -P 随机生成端口映射 
docker run -d -P --name nginx01 -v /etc/nginx nginx

# 查看所有卷的情况:
docker volume ls

# 这里发现,这种就是匿名挂载。我们使用 -v 只写了容器内的路径,没有写容器外的路径!会自动生成一个匿名的

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

# 查看卷情况
docker volume ls

# 查看这个卷具体信息
docker volume inspect 卷名

# 所有的docker容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volumes/xxxx/_data
# 如何确定是具名挂载还是匿名挂载,还是指定路径挂载
-v 容器内路径			   # 匿名挂载
-v 卷名:容器内路径			  # 具名挂载
-v /宿主机路径:容器内路径		# 指定路径挂载

拓展:

# 通过 -v 容器内路径;ro  rw  改变读写权限
# ro	readonly	只读,只能在容器外部修改
# rw	readwrite	可读可写,默认是rw


# 一旦设置了容器权限,容器对我们挂载出来的内容就有限定了
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx

初识DockerFile

DockerFile使用来构建docker镜像的文件!命令脚本!

# 镜像是一层一层的,脚本是一行一行的
# 指令都是大写的
# 这里的每个命令可以理解为镜像的一层

FROM centos

VOLUME ["volume01","volume02"] # 再创建镜像的时候就挂载出来

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

# 构建build镜像
docker build -f dockerfile1 -t padaxing/centos:1.0 .  # 最后的点很重要 镜像名不能有/

容器内自动挂载的目录

这种方式我们未来使用的十分多,因为我们通常会构建自己的镜像!

假设构建镜像时没有挂载卷,要手动镜像挂载 -v 卷名:容器内路径!

多个容器数据共享

多个mysql同步数据! 利用 --volumes-from 命令

原理

# 测试
# 启动docker01,用之前建的padaxing/centos 1.0  镜像
docker run -it --name docker01 padaxing/centos:1.0 	 # 1.0必须写

# 当前这个ctrl+p+q不停止退出

# 依次启动docker02、docker03
docker run -it --name docker02 --volumes-from docker01 padaxing/centos:1.0
docker run -it --name docker03 --volumes-from docker01 padaxing/centos:1.0

# docker02继承docker01的volumes。可以验证,在docker01下加一个数据,在docker02下也会出现
# 在docker03的volume01下建立文件,在docker01的volume01下同样也有

# 即通过--volumes-from 可以实现不同容器间的数据共享

# 删除docker01,数据还在


# 原因:实际类似于硬链接。三个(多个)容器挂载到宿主机的相同卷,可通过 docker inspect 查看,容器卷关在在宿主机的同一目录下(即source相同)。所以即使删除一个容器,宿主机本地目录不会被删除,则不影响其它使用的容器数据。

结论:

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

但是如果持久化 -v 到了本地,即使所有容器删除了,本地数据是不会删除的。

DockerFile

步骤:开发、部署、运维。。。。缺一不可

​ DockerFile:构建文件。定义了一切的步骤,源代码

​ DockerImages:通过DockerFile构建生成的镜像,最终发布和运行的产品!

​ Docker容器:容器是镜像运行起来提供服务的

DockerFile介绍

是用来构建docker镜像的文件,可以理解为命令参数脚本

构建步骤:

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

这和写一个项目时一样的。

查看官方的DockerFile文件,可以在Docker Hub中查找镜像(下图)。选择一个版本,会跳转到github中的dockerfile文件。

可以看到官方镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像。

DockerFile基础知识

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

docker是面向开发的,我们以后要发布项目,做镜像,就要编写dockerfile文件,这个文件十分简单!

Docker镜像逐渐成为企业的交付标准,必须掌握!

DockerFile命令

FROM 		# 基础镜像 比如centos
MAINTAINER  # 镜像是谁写的 姓名+邮箱
RUN 		# 镜像构建时需要运行的命令
ADD 		# 添加,比如添加一个tomcat压缩包
WORKDIR 	# 镜像的工作目录
VOLUME 		# 挂载的目录
EXPOSE 		# 指定暴露端口,跟-p一个道理
RUN 		# 最终要运行的
CMD 		# 指定这个容器启动的时候要运行的命令,只有最后一个(一个CMD中的最后一个命令)会生效,而且可被替代
ENTRYPOINT  # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD 	# 它后面跟的是其它指令,比如 RUN, COPY 等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行
COPY 		# 将文件拷贝到镜像中
ENV 		# 构建的时候设置环境变量

实战构建自己的centos

Docker Hub中99%的镜像都是从 FROM scratch 开始的

# 创建dockerfile文件,并编辑
root@ecs-7ed1:~# mkdir dockerfile
root@ecs-7ed1:~# cd dockerfile/
root@ecs-7ed1:~/dockerfile# ls
root@ecs-7ed1:~/dockerfile# vim mydocker-centos

# dockerfile文件内容
FROM centos
MAINTAINER padaxing<010301200@hai.com>

ENV MYPATH /usr/local
WORKDIR $MYPATH

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

EXPOSE 80

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

# 构建镜像
docker build -f mydocker-centos -t mycentos:0.1 .

Successfully built b08c93da098f
Successfully tagged mycentos:0.1

# 测试构建的镜像

root@ecs-7ed1:~/dockerfile# docker run -it mycentos:0.1
[root@1cc49b0f5af5 local]# ls
bin  etc  games  include  lib  lib64  libexec  sbin  share  src
[root@1cc49b0f5af5 local]# pwd
/usr/local						# 与dockerfile文件中的WORKDIR $MYPATH 相同
[root@1cc49b0f5af5 local]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 11  bytes 906 (906.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

对比之前的原生centos,很多命令vim,ifconfig都可以执行了。

可以通过docker history查看镜像的构建历史

root@ecs-7ed1:~/dockerfile# docker history b08c93da098f
IMAGE          CREATED          CREATED BY                                      SIZE      COMMENT
b08c93da098f   12 minutes ago   /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "/bin…   0B
fa0807f4d458   12 minutes ago   /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B
178c87492d73   12 minutes ago   /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B
529bdb7fd679   12 minutes ago   /bin/sh -c #(nop)  EXPOSE 80                    0B
2254913a6535   12 minutes ago   /bin/sh -c yum -y install net-tools             29.5MB
357ec9e0edec   12 minutes ago   /bin/sh -c yum -y install vim                   68.1MB
eac37e85f6e8   12 minutes ago   /bin/sh -c #(nop) WORKDIR /usr/local            0B
74ed128d823b   12 minutes ago   /bin/sh -c #(nop)  ENV MYPATH=/usr/local        0B
15c22d1110f2   12 minutes ago   /bin/sh -c #(nop)  MAINTAINER padaxing<01030…   0B
300e315adb2f   8 months ago     /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>      8 months ago     /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B
<missing>      8 months ago     /bin/sh -c #(nop) ADD file:bd7a2aed6ede423b7…   209MB

CMD与ENTRYPOINT

CMD 		# 指定这个容器启动的时候要运行的命令,只有最后一个(一个CMD中的最后一个命令)会生效,而且可被替代
ENTRYPOINT  # 指定这个容器启动的时候要运行的命令,可以追加命令
# 测试CMD
# CMD [] :要运行的命令是存放在一个数组结构中的
# build镜像
FROM centos
CMD ["ls","-a"] # 启动centos展示目录

测试CMD

# 测试ENTRYPOINT

测试ENTRYPOINT

run的时候可以直接加命令

实战:Tomcat镜像

1、准备镜像文件 tomcat 压缩包,jdk的压缩包!

image-20210903200158699

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

image-20210903200813909

tail -F 文件名 : tail命令启动时,文件不可访问或者文件稍后变得不可访问,都始终尝试打开文件

3、构建镜像

# docker build -t diytomcat .

4、启动镜像

image-20210903203230703

5、访问测试

6、发布项目(由于做了卷挂载,我们直接在本地编写项目就可以发布了!)

image-20210903202855576

# 先创建web.xml 和 index.jsp 文件

# 首先简单讲一下,web.xml的加载过程。当启动一个WEB项目时,容器包括(JBoss、Tomcat等)首先会读取项目web.xml配置文件里的配置,当这一步骤没有出错并且完成之后,项目才能正常地被启动起来。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0"
         metadata-complete="true">
</web-app>

# index.jsp文件内容
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<body>
Hello World!<br/>
<%
out.println("你的 IP 地址 " + request.getRemoteAddr());
%>
</body>
</html>

发布项目之后测试

image-20210903203258935

打印日志测试

cat catalina.out

image-20210903203508729

发布自己的镜像

至DockerHub

1、地址 https://registry.hub.docker.com/ 注册自己的账号

2、确定这个账号可以登录

3、在我们服务器上登陆自己的账号

docker login -u 用户名 -p 密码

4、登陆完毕后就可以一觉自己的镜像了,,docker push命令

docker push 用户名/镜像名:tag		# 必须带tag

# 给镜像增加tag
docker tag 镜像id 新镜像名:修改的tag

提交的时候也是按照镜像的层级来进行提交的

至阿里云镜像服务上

1、登陆阿里云

2、找到容器镜像服务

3、创建命名空间

4、创建容器镜像

小结

docker所有流程

Docker网络(铺垫 容器编排 集群部署!)

参考:

Docker网络详解——原理篇

veth-pair详解

网络模式 简介
Host 容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。
Bridge 此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,通过docker0网桥以及Iptables nat表配置与宿主机通信。
None 该模式关闭了容器的网络功能。
Container 创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围。
自定义网络

测试

**查看宿主机IP信息**

测试linux能否ping通容器内部

测试linux能否ping通容器内部

image-20210903222746080

再次测试ip addr

image-20210906095453969

再启动一个容器测试,发现又多了一对网卡

image-20210906100636980

# 我们发现这个容器带来网卡,都是成对出现
# evth-pair 就是一对的虚拟设备接口,它们都是成对出现的,一段连着协议,一段彼此相连
# 正因为有这个特性,evth-pair 充当一个桥梁,连接各种虚拟网络设备的
# Openstack,Docker容器之间的连接,OVS的连接,都是使用evth-pair技术

测试两个容器之间是否可以ping通

# 测试,可以ping通
root@ecs-7ed1:~# docker exec -it 1cc49b0f5af5 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.129 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.054 ms
64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.053 ms
64 bytes from 172.17.0.3: icmp_seq=4 ttl=64 time=0.053 ms
^C
--- 172.17.0.3 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 71ms
rtt min/avg/max/mdev = 0.053/0.072/0.129/0.033 ms

原理图:

image-20210906102508624

结论:容器之间有一个公用的路由器,docker 0

所有的容器在不指定网络的情况下,都是docker 0 路由的,docker会给我们的容器分配一个默认的可用IP

255.255.0.1/16

00000000.00000000.00000000.00000000

255.255.255.255

小结

Docker 使用的是Linux的桥接,宿主机中是一个Docker容器的网桥,docker 0

原理

image-20210906103308478

Docker 中的所有的网络接口都是虚拟的。虚拟的转发效率高!

只要容器删除,对应的网桥一对就没了

- -link

思考 一个场景,我们编写了一个微服务,database url = ip , 项目不重启,数据库ip换掉了,我们希望可以处理这个问题,可以用名字来进行访问容器?

# 直接用容器名ping,失败
root@ecs-7ed1:~# docker exec -it romantic_dirac ping centosce
ping: centosce: Name or service not known

# --link 命令解决
root@ecs-7ed1:~# docker run -it -P --name centosce02 --link centosce mycentos:0.1
[root@2f62396223e0 local]# ping centosce
PING centosce (172.17.0.3) 56(84) bytes of data.
64 bytes from centosce (172.17.0.3): icmp_seq=1 ttl=64 time=0.111 ms
64 bytes from centosce (172.17.0.3): icmp_seq=2 ttl=64 time=0.056 ms
64 bytes from centosce (172.17.0.3): icmp_seq=3 ttl=64 time=0.057 ms
64 bytes from centosce (172.17.0.3): icmp_seq=4 ttl=64 time=0.057 ms
^C
--- centosce ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 54ms
rtt min/avg/max/mdev = 0.056/0.070/0.111/0.024 ms
[root@2f62396223edocker exec -it centosce02 ping centosce
PING centosce (172.17.0.3) 56(84) bytes of data.
64 bytes from centosce (172.17.0.3): icmp_seq=1 ttl=64 time=0.065 ms
64 bytes from centosce (172.17.0.3): icmp_seq=2 ttl=64 time=0.062 ms
64 bytes from centosce (172.17.0.3): icmp_seq=3 ttl=64 time=0.059 ms
^C
--- centosce ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 49ms
rtt min/avg/max/mdev = 0.059/0.062/0.065/0.002 ms


# 测试反向是否能ping通,失败
root@ecs-7ed1:~# docker exec -it centosce ping centosce02
ping: centosce02: Name or service not known

探究,docker network inspect NETWORKID

image-20210906111324168

image-20210906111457271

利用docker inspect 容器ID,查看centosce02 本地配置了centosce容器的配置

image-20210906112340998

# 查看 hosts 配置,在这里发现原理
root@ecs-7ed1:~# docker exec -it centosce02 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      centosce 96b487627e1f		# 绑定
172.17.0.4      2f62396223e0

# 本质:--link 就是我们在 hosts 配置中增加了 172.17.0.3 centosce 96b487627e1f 映射

我们现在玩Docker 已经不建议使用 --link 了!

自定义网络!不适用docker0

docker0 问题:它不支持容器名连接访问!

自定义网络

# 查看所有的docker网络

root@ecs-7ed1:~# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
8aea018330c0   bridge    bridge    local
98037768e9fc   host      host      local
88801a794175   none      null      local

网络模式

网络模式 简介
Host 容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。
Bridge 此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,通过docker0网桥以及Iptables nat表配置与宿主机通信。
None 该模式关闭了容器的网络功能。
Container 创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围。
自定义网络

测试

# 我们直接启动的命令默认是桥接模式  --net bridge,就是我们的docker0
root@ecs-7ed1:~# docker run -d -P --name tomcat01 tomcat
root@ecs-7ed1:~# docker run -d -P --name tomcat01 --net bridge tomcat

# docker0 特点,默认,域名不能访问, --link可以打通连接

# 我们可以自定义一个网络
# --driver bridge
# --subnet 192.168.0.0/16  子网地址(192.168.0.2~192.168.255.255)
# --gateway 192.168.0.1 网关(路由器)
root@ecs-7ed1:~# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
ec634260bc6868ccd491bb9126249d7e811b6946aa2d3462b19eb34b05e17c4e
root@ecs-7ed1:~# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
8aea018330c0   bridge    bridge    local
98037768e9fc   host      host      local
ec634260bc68   mynet     bridge    local
88801a794175   none      null      local

# 我们自己的网络就创建好了

# 通过自己创建的网络创建两个容器
root@ecs-7ed1:~# docker run -it -P --name centos-net-01 --net mynet mycentos:0.1

root@ecs-7ed1:~# docker run -it -P --name centos-net-02 --net mynet mycentos:0.1

# 查看网络信息
root@ecs-7ed1:~# docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "ec634260bc6868ccd491bb9126249d7e811b6946aa2d3462b19eb34b05e17c4e",
        "Created": "2021-09-06T14:19:41.156516116+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "9d92a018707dd27653c68d52acefa18b7c8acda30c535ec9f1cee8a47bee3591": {
                "Name": "centos-net-01",
                "EndpointID": "c60296191820dcdbab953bb82cb37eb81547730ad6a5cf9ec182b4794a3da5bf",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/16",
                "IPv6Address": ""
            },
            "f9b17003373507e68042d16293514be760ba76c2f135a24bf2c01f9de6ae5c2c": {
                "Name": "centos-net-02",
                "EndpointID": "a90ef766d1f22a816443271372b6e0bedff6db20d61d2b953b24b1365835ed57",
                "MacAddress": "02:42:c0:a8:00:03",
                "IPv4Address": "192.168.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

# 测试两个容器之间能不能 ping 通
# ping IP,成功
root@ecs-7ed1:~# docker exec -it centos-net-01 ping 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.090 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.063 ms
64 bytes from 192.168.0.3: icmp_seq=3 ttl=64 time=0.059 ms
^C
--- 192.168.0.3 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 32ms
rtt min/avg/max/mdev = 0.059/0.070/0.090/0.016 ms

# ping 容器名,成功。  不使用--link,也可以
root@ecs-7ed1:~# docker exec -it centos-net-01 ping centos-net-02
PING centos-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from centos-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.087 ms
64 bytes from centos-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.054 ms
64 bytes from centos-net-02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.057 ms
^C
--- centos-net-02 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 28ms
rtt min/avg/max/mdev = 0.054/0.066/0.087/0.014 ms

创建网络之后查看ip addr

创建网络之后查看ip addr

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

好处:

redis - 不同的集群使用不同的网络,保证集群是安全和健康的。

mysql - 不同的集群使用不同的网络,保证集群是安全和健康的。

网络连通

测试不同网络下的容器之间 ping 不通。

root@ecs-7ed1:~# docker exec -it centos01 ping centos-net-01
ping: centos-net-01: Name or service not known

须使用connect将容器与网络连接

image-20210906151142901

Usage:  docker network connect [OPTIONS] NETWORK CONTAINER

# 测试打通 centos01 到 mynet
root@ecs-7ed1:~# docker network connect mynet centos01

# 查看网络信息,发现容器处多一个centos01
# 连通之后就是将 centos01 放到了 mynet 网络下
# 就是一个容器两个 IP地址! --一个在bridge网络下 172.17.0.2;一个在mynet网络下 192.168.0.4
# 类似阿里云服务器:公网IP   私网IP
root@ecs-7ed1:~# docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "ec634260bc6868ccd491bb9126249d7e811b6946aa2d3462b19eb34b05e17c4e",
        "Created": "2021-09-06T14:19:41.156516116+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "866174b67e0091714db22f309d5e7aec813cd0403d2e4156ef4bfe4b9b3ab880": {
                "Name": "centos01",
                "EndpointID": "b53e1e14d4dc2fbeff12fd073ebb3b6e336c98d7f574fa91e99ccf7b5392b16e",
                "MacAddress": "02:42:c0:a8:00:04",
                "IPv4Address": "192.168.0.4/16",
                "IPv6Address": ""
            },
            "9d92a018707dd27653c68d52acefa18b7c8acda30c535ec9f1cee8a47bee3591": {
                "Name": "centos-net-01",
                "EndpointID": "c60296191820dcdbab953bb82cb37eb81547730ad6a5cf9ec182b4794a3da5bf",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/16",
                "IPv6Address": ""
            },
            "f9b17003373507e68042d16293514be760ba76c2f135a24bf2c01f9de6ae5c2c": {
                "Name": "centos-net-02",
                "EndpointID": "a90ef766d1f22a816443271372b6e0bedff6db20d61d2b953b24b1365835ed57",
                "MacAddress": "02:42:c0:a8:00:03",
                "IPv4Address": "192.168.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

# 测试是否能ping 通,成功!!
root@ecs-7ed1:~# docker exec -it centos01 ping centos-net-01
PING centos-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from centos-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.129 ms
64 bytes from centos-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.059 ms
64 bytes from centos-net-01.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.058 ms
^C
--- centos-net-01 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 28ms
rtt min/avg/max/mdev = 0.058/0.082/0.129/0.033 ms

**结论:**假设要通过网络操作其它容器,就需要使用 docker network connect 连通!

实战:部署Redis集群

image-20210906152424537

# 创建 redis 网络
docker network create redis --subnet 172.38.0.0/16

# 通过shell脚本创建六个redis配置
for port in $(seq 1 6); \
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF  >/mydata/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.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done

# 创建6个容器,节点
docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
    -v /mydata/redis/node-1/data:/data \
    -v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
    -d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    
docker run -p 6372:6379 -p 16372:16379 --name redis-2 \
    -v /mydata/redis/node-2/data:/data \
    -v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
    -d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    
docker run -p 6373:6379 -p 16373:16379 --name redis-3 \
    -v /mydata/redis/node-3/data:/data \
    -v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \
    -d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    
docker run -p 6374:6379 -p 16374:16379 --name redis-4 \
    -v /mydata/redis/node-4/data:/data \
    -v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \
    -d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    
docker run -p 6375:6379 -p 16375:16379 --name redis-5 \
    -v /mydata/redis/node-5/data:/data \
    -v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \
    -d --net redis --ip 172.38.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    
docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
    -v /mydata/redis/node-6/data:/data \
    -v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
    -d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    
# 创建集群
root@ecs-7ed1:~# docker exec -it redis-1 /bin/sh
/data # ls
appendonly.aof  nodes.conf
/data # redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.
15:6379 172.38.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.38.0.15:6379 to 172.38.0.11:6379
Adding replica 172.38.0.16:6379 to 172.38.0.12:6379
Adding replica 172.38.0.14:6379 to 172.38.0.13:6379
M: d5f38eac055b1f200776b4d8f6e294fdbe6adfec 172.38.0.11:6379
   slots:[0-5460] (5461 slots) master
M: 1391c63afef978e7c8db20a221d6f11865cd543a 172.38.0.12:6379
   slots:[5461-10922] (5462 slots) master
M: aea97f79ad407ada284118f33e5622e1ffaf369a 172.38.0.13:6379
   slots:[10923-16383] (5461 slots) master
S: 8bb7d0eb00a8924f67a6bfbe46019875d024c05b 172.38.0.14:6379
   replicates aea97f79ad407ada284118f33e5622e1ffaf369a
S: 01f579678eed6ebd4de339c52ced69958b6935fe 172.38.0.15:6379
   replicates d5f38eac055b1f200776b4d8f6e294fdbe6adfec
S: 2da4d51a9b21c84c6e06dade77310d830e4e9e0f 172.38.0.16:6379
   replicates 1391c63afef978e7c8db20a221d6f11865cd543a
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.38.0.11:6379)
M: d5f38eac055b1f200776b4d8f6e294fdbe6adfec 172.38.0.11:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
M: 1391c63afef978e7c8db20a221d6f11865cd543a 172.38.0.12:6379
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: 01f579678eed6ebd4de339c52ced69958b6935fe 172.38.0.15:6379
   slots: (0 slots) slave
   replicates d5f38eac055b1f200776b4d8f6e294fdbe6adfec
M: aea97f79ad407ada284118f33e5622e1ffaf369a 172.38.0.13:6379
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: 2da4d51a9b21c84c6e06dade77310d830e4e9e0f 172.38.0.16:6379
   slots: (0 slots) slave
   replicates 1391c63afef978e7c8db20a221d6f11865cd543a
S: 8bb7d0eb00a8924f67a6bfbe46019875d024c05b 172.38.0.14:6379
   slots: (0 slots) slave
   replicates aea97f79ad407ada284118f33e5622e1ffaf369a
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

# 测试,在redis-3中set a值,然后停止运行redis-3。再次 get a值 ,返回成功。是从 从机 redis-4 中获取的值

节点主从信息

节点主从信息

停止 redis-3 后,在从机 redis-4 中查到a值

停止 redis-3 后,在从机 redis-4 中查到a值

再次查看节点信息,发现 redis-3已经fail,故障转移。redis-4变成master

image-20210907155038672

SpringBoot微服务打包Docker镜像

狂神docker-39-SpringBoot微服务打包Docker镜像

Docker进阶

Docker Compose

简介

原来:dockerfile -> build -> run 手动操作,单个容器!

若 微服务,100个微服务!依赖关系。 很难实现

Docker 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. To learn more about all the features of Compose, see the list of features. (定义和运行多容器、YMAL配置文件、命令)

Compose works in all environments: production, staging, development, testing, as well as CI workflows. You can learn more about each case in Common Use Cases.

Using Compose is basically a three-step process:

  1. Define your app’s environment with a Dockerfile so it can be reproduced anywhere. (Dockerfile保证我们的项目在任何地方可以运行)
  2. Define the services that make up your app in docker-compose.yml so they can be run together in an isolated environment. (services 什么是服务、docker-compose.yml 文件怎么写)
  3. Run docker compose up and the Docker compose command starts and runs your entire app. You can alternatively run docker-compose up using the docker-compose binary. (启动项目)

作用:批量容器编排。

kaungshen:

Compose 是Docker官方的开源项目,需要安装!

Dockerfile保证我们的项目在任何地方可以运行。 web服务、redis、mysql、nginx…多个容器。 需要多个build & run

Compose:重要概念

  • 服务services:容器、应用。(web、redis、mysql…)
  • 项目project。一组关联的容器。
# Compose.yml 文件举例。	两个服务web、redis。web links redis
version: "3.9"  # optional since v1.27.0
services:
  web:				
    build: .
    ports:
      - "5000:5000"
    volumes:
      - .:/code
      - logvolume01:/var/log
    links:
      - redis
  redis:
    image: redis
volumes:
  logvolume01: {}
  
# docker-compose up 100个服务!!

安装Compose

# 1、下载
 sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
 
 # 2、授权
 sudo chmod +x /usr/local/bin/docker-compose
 
 # 3、检查是否安装成功
 docker-compose version

体验——官网文档实战

体验项目地址----Docker官网文档 —python应用。计数器。redis!

# 1、为项目创建目录
# 2、创建app.py文件:应用
# 3、创建依赖包
# 4、创建Dockerfile文件:应用打包为镜像
# 5、创建yml文件,定义服务(服务需要的环境,完整的上线服务)
# 6、启动项目build and run
	docker-compose up
	
# 7、测试,成功
root@ecs-7ed1:~# curl localhost:5000
Hello World! I have been seen 1 times.

自动的默认规则

查看镜像 docker images ——自动下载

# 查看镜像  docker images  ——自动下载
root@ecs-7ed1:~# docker images
REPOSITORY            TAG                IMAGE ID       CREATED          SIZE
composetest_web       latest             b878a824af5d   11 minutes ago   184MB
<none>                <none>             7dc492a51c16   2 hours ago      41.9MB
redis                 alpine             f6f2296798e9   11 days ago      32.3MB
python                3.7-alpine         ab6374cb8b8e   11 days ago      41.9MB

# docker service ls
root@ecs-7ed1:~# docker service ls
Error response from daemon: This node is not a swarm manager. Use "docker swarm init" or "docker swarm join" to connect this node to swarm and try again.

默认的服务名 : 文件名_服务名_num

多个服务器。集群。A B _num 副本数量

服务redis服务 => 4 个副本

集群状态。服务都不可能只有一个运行实例。弹性、HA(高可用集群)、高并发

kubectl service 负载均衡。

3、网络规则

# 查看网络,新建composetest_default网络
root@ecs-7ed1:~# docker network ls
NETWORK ID     NAME                  DRIVER    SCOPE
8aea018330c0   bridge                bridge    local
14b69e745911   composetest_default   bridge    local
98037768e9fc   host                  host      local
ec634260bc68   mynet                 bridge    local
88801a794175   none                  null      local
dbd3209213ec   redis                 bridge    local

# 查看composetest_default网络,有web_1、redis_1容器
root@ecs-7ed1:~# docker network inspect composetest_default
[
    {
        "Name": "composetest_default",
        "Id": "14b69e74591176587aa499e1295dd76830870b4376a379639d7c7f858672720d",
        "Created": "2021-09-08T10:45:50.492279984+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": true,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "9f0b074df478b53b0e1f14bc70ebdd2e8892b6c5db201c1b4f1d1617127ba990": {
                "Name": "composetest_web_1",
                "EndpointID": "db66e6645c02fe592e4d12d93ea15a45d1f4836c7bb00935e3c91ed56d295ad6",
                "MacAddress": "02:42:ac:12:00:03",
                "IPv4Address": "172.18.0.3/16",
                "IPv6Address": ""
            },
            "a30b19e67d705949e24c03167af6c45d1944f0ee96bb74de168ef028c9989b28": {
                "Name": "composetest_redis_1",
                "EndpointID": "62578f91ce49569554d84cb60a6cb3c4330c0f5126507fc498cf8644d7890646",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {
            "com.docker.compose.network": "default",
            "com.docker.compose.project": "composetest",
            "com.docker.compose.version": "1.29.2"
        }
    }
]

10个服务 => 项目 (项目中的内容都在同个网络下。域名访问)

mysql : 3306 ——> 通过mysql去访问,而不是通过ip。

如果在同一个网络下,我们可以直接通过域名访问。保证高可用

停止:

  • 直接 Ctrl + C
  • docker-compose down

yaml规则

docker-compose.yaml 核心!!!

参考 : 官方文档

多写多看:1、官方文档;2、开源项目

# 3层!

version:'' 	# 1、版本
services:	# 2、服务
   服务1: web
	# 服务配置	docker容器的配置
	images
	build
	network
	......
   服务2: redis
   	......
   服务3: redis
   	......
# 3、其它配置  网络/卷、全局规划
volumes:
network:
configs:

depends_on

depends_on

deploy

deploy

开源项目——wordpress

博客wordpress: 官方文档wordpress博客项目

下载程序、安装数据库、配置…

compose应用 => 一键启动!

1、下载项目(docker-compose.yaml)

2、如果需要文件。Dockerfile

3、文件准备齐全(直接一键启动项目!)

测试,成功

image-20210910105303113

前台启动 docker-compose up

后台启动 docker-compose up -d

实战

步骤:

  1. 编写项目微服务
  2. Dockerfile 构建镜像
  3. docker-compose.yml 编排项目
  4. 丢到服务器 一键启动:docker-compose up

假设项目要重新部署打包

docker-compose up --build	# 重新构建!

总结:

项目 compose :三层

  • 工程 Project
  • 服务
  • 容器 运行实例! docker k8s

Docker Swarm

参考 : 官方文档

掌握 搭建集群、启动服务、动态管理容器

工作模式

Docker Engine 1.12 introduces swarm mode that enables you to create a cluster of one or more Docker Engines called a swarm. A swarm consists of one or more nodes: physical or virtual machines running Docker Engine 1.12 or later in swarm mode.

There are two types of nodes: managers and workers.

Swarm mode cluster

If you haven’t already, read through the swarm mode overview and key concepts.

  • 节点:管理节点、工作节点
  • Raft一致性算法
  • 操作都在manager

搭建集群

# 4个节点,两主两从
# manager节点
[root@k8s-master ~]# docker swarm init --advertise-addr 192.168.142.111
Swarm initialized: current node (lsmof9xcbrhxgtego47r7c8kk) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-103kz9hhfiohrq4tlara8w34n1qah8ciqlod9qvgtsbp9fqqmg-dvju5jbd4hlv7aroqr1i7neno 192.168.142.111:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

# 两个从节点
[root@k8s-node1 ~]#  docker swarm join --token SWMTKN-1-103kz9hhfiohrq4tlara8w34n1qah8ciqlod9qvgtsbp9fqqmg-dvju5jbd4hlv7aroqr1i7neno 192.168.142.111:2377
This node joined a swarm as a worker.

# 在manager节点测试
[root@k8s-master ~]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
lsmof9xcbrhxgtego47r7c8kk *   k8s-master          Ready               Active              Leader              18.06.1-ce
nei92zfk2sy9u71yx425sz1sp     k8s-node1           Ready               Active                                  18.06.1-ce
whidxgyl1dbedftspqrd6mga4     k8s-node3           Ready               Active                                  18.06.1-ce

# 加入manager节点,先获取令牌token
[root@k8s-master ~]# docker swarm join-token manager
To add a manager to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-103kz9hhfiohrq4tlara8w34n1qah8ciqlod9qvgtsbp9fqqmg-2vokifkkn0d7lolh9fzs801gc 192.168.142.111:2377

# 在新增manager节点执行命令
[root@k8s-node3 ~]# docker swarm join --token SWMTKN-1-103kz9hhfiohrq4tlara8w34n1qah8ciqlod9qvgtsbp9fqqmg-dvju5jbd4hlv7aroqr1i7neno 192.168.142.111:2377
This node joined a swarm as a worker.

# 在manager节点测试
[root@k8s-master ~]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
lsmof9xcbrhxgtego47r7c8kk *   k8s-master          Ready               Active              Leader              18.06.1-ce
nei92zfk2sy9u71yx425sz1sp     k8s-node1           Ready               Active                                  18.06.1-ce
gl8jytd5om2fizqvmlt6n1ilr     k8s-node2           Ready               Active              Reachable           18.06.1-ce
whidxgyl1dbedftspqrd6mga4     k8s-node3           Ready               Active                                  18.06.1-ce

常见错误:

# 1.x509: certificate has expired or is not yet valid
时间不同步问题
# 2.error: connection error: desc = "trt: no route to host"
关闭manager防火墙:  systemctl stop firewalld

加入 新的节点!

# 获取令牌
docker swarm join-token manager
docker swarm join-token worker

Raft一致性协议

双主双从:假设一个节点挂了! 其他节点是否可用???

Raft协议:保证大多数节点存活才可以用。。存活的节点数至少 > 1 ,则集群至少 大于3台!

实验:

  1. 将docker master1 机器停止,宕机! 由于是双主,另外一个主节点也不能使用了!

    # 在manager1 上停止docker
    [root@k8s-master ~]# systemctl stop docker
    
    # 在另一台manager节点上测试,失败
    [root@k8s-node2 ~]# docker node ls
    Error response from daemon: rpc error: code = DeadlineExceeded desc = context deadline exceeded# 
    
    # 原因:存活节点==1
    
    # 再次启动原manager1,测试,发现本节点不再是leader,原Reachable变成Leader
    [root@k8s-master ~]# systemctl start docker
    [root@k8s-master ~]# docker node ls
    ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
    lsmof9xcbrhxgtego47r7c8kk *   k8s-master          Ready               Active              Reachable           18.06.1-ce
    nei92zfk2sy9u71yx425sz1sp     k8s-node1           Ready               Active                                  18.06.1-ce
    gl8jytd5om2fizqvmlt6n1ilr     k8s-node2           Ready               Active              Leader              18.06.1-ce
    whidxgyl1dbedftspqrd6mga4     k8s-node3           Ready               Active                                  18.06.1-ce
    
  2. 可以其他节点离开

    docker swarm leave命令,Ready 变成 Down

    image-20210910152045430

  3. 工作在work节点,管理在manager!

  4. 设置成3个manager节点,实验是否高可用!

    # 同 1 实验。关闭 当前leader节点,在其他manager节点测试,发现,可正常操作
    [root@k8s-node2 ~]# systemctl stop docker
    
    # k8s-node1上测试
    [root@k8s-node1 ~]# docker node ls
    ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
    lsmof9xcbrhxgtego47r7c8kk     k8s-master          Ready               Active              Leader              18.06.1-ce
    81n0ez1ljhfr5fgua26ju695k *   k8s-node1           Ready               Active              Reachable           18.06.1-ce
    nei92zfk2sy9u71yx425sz1sp     k8s-node1           Down                Active                                  18.06.1-ce
    gl8jytd5om2fizqvmlt6n1ilr     k8s-node2           Down                Active              Unreachable         18.06.1-ce
    whidxgyl1dbedftspqrd6mga4     k8s-node3           Ready               Active                                  18.06.1-ce
    

当重启所有虚拟机后,发现再次使用 docker node ls 命令,报错:

Error: rpc error: code = Unknown desc = The swarm does not have a leader. It’s possible that too few managers are online. Make sure more than half of the managers are online.

# 处理:在一台manager节点上使用命令
[root@k8s-master ~]# docker swarm init --force-new-cluster
Swarm initialized: current node (lsmof9xcbrhxgtego47r7c8kk) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-103kz9hhfiohrq4tlara8w34n1qah8ciqlod9qvgtsbp9fqqmg-dvju5jbd4hlv7aroqr1i7neno 192.168.142.111:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

命令docker swarm init --force-new-cluster需要在一台活着的manager节点上执行,其含义是:

  1. 在执行命令的node上重新初始化swarm cluster
  2. 这个cluster只包含当前自己一个node
  3. 这个cluster会试图重新创建所有的services (它本身是manager节点,包含之前所有的cluster信息)
  4. 这个cluster会把还活着的其他manager节点和worker节点自动加进来

体会——服务 service

弹性、扩缩容!集群!

以后告别 docker run!

docker-compose up! 启动一个项目!

集群:swarm! docker service

容器 = > 服务!

容器 = > 服务! = > 副本!

redis 服务 => 10个副本! (同时开启10个redis容器)

# docker service 创建服务、动态扩展服务、动态更新服务

image-20210912141512634

灰度发布:金丝雀发布! ——升级不影响使用!

docker run   	# 容器启动!不具有扩缩容
docker service 	# 服务!  具有扩缩容、滚动更新!
# 启动服务service
[root@k8s-master ~]# docker service create -p 8888:80 --name my-nginx nginx
fhn2mxqa8tdwxqz5w7lkxqxe5
overall progress: 1 out of 1 tasks
1/1: running   [==================================================>]
verify: Service converged

# 查看服务
[root@k8s-master ~]# docker service ps my-nginx
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE                ERROR               PORTS
idbm3cir2u0z        my-nginx.1          nginx:latest        k8s-node1           Running             Running about a minute ago

[root@k8s-master ~]# docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
fhn2mxqa8tdw        my-nginx            replicated          1/1                 nginx:latest        *:8888->80/tcp

# REPLICAS 副本,此时为 1
# 在其它三个节点中 使用 docker ps 命令,查看副本运行在哪个节点
[root@k8s-node1 ~]# docker ps
CONTAINER ID        IMAGE                                               COMMAND                  CREATED             STATUS              PORTS               NAMES
bdf887a6ad51        nginx:latest                                        "/docker-entrypoint.…"   3 minutes ago       Up 3 minutes        80/tcp              my-nginx.1.idbm3cir2u0zvrxao1v1ynalu

# 创建更多的副本
# 1、使用docker service update --replicas 3 my-nginx
[root@k8s-master ~]# docker service update --replicas 3 my-nginx
my-nginx
overall progress: 3 out of 3 tasks
1/3: running   [==================================================>]
2/3: running   [==================================================>]
3/3: running   [==================================================>]
verify: Service converged
# 查看副本运行情况
[root@k8s-master ~]# docker service ps my-nginx
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
idbm3cir2u0z        my-nginx.1          nginx:latest        k8s-node1           Running             Running 4 minutes ago
0u03mamg3syo        my-nginx.2          nginx:latest        k8s-master          Running             Running 3 minutes ago
vxsdfiokn1mf        my-nginx.3          nginx:latest        k8s-node2           Running             Running 4 minutes ago

# 2、使用 scale 命令
[root@k8s-master ~]# docker service scale my-nginx=5
my-nginx scaled to 5
overall progress: 5 out of 5 tasks
1/5: running   [==================================================>]
2/5: running   [==================================================>]
3/5: running   [==================================================>]
4/5: running   [==================================================>]
5/5: running   [==================================================>]
verify: Service converged

# update --replicas num 命令与 scale 命令区别
# 测试发现并无差别,两者缩容时,都会将容器删除rm
# update更多的应用场景在于image的升级导致的运行中的服务需要更新等等

遇见的问题:创建副本时,一直卡在preparing状态

image-20210912152518063

处理方法: docker service 卡在 prepering 状态

# 移除 服务
[root@k8s-master ~]# docker service rm my-nginx
my-nginx

服务,集群中的任意的节点都可以访问。服务可以有多个副本动态扩缩容实现高可用!

弹性、扩缩容!

swarm => k8s 副本、服务器、多容器!

概念总结

  • swarm

    集群的管理和编号。docker 可以初始化一个 swarm 集群,其他节点可以加入。(manager、worker)

  • Node

    就是一个 docker 节点。多个节点姐组成一个网络集群。(manager、worker)

  • Service

    任务,可以在管理节点或者工作节点来运行。**核心!**用户访问

  • Task

    容器内的命令,细节任务!

image-20210912154806958

image-20210912155404357

命令执行细节命令 --> 管理 --> API --> 调度 --> 工作节点(创建Task容器,维护创建!)

逻辑是不变的,对比K8S

  • 不同模式

不同模式

# replicated 与 global
# replicated 内部调度器则会根据当前集群的资源使用情况在不同的node上启停容器
# global 强制在每个node上都运行一个且最多一个副本

# --mode string
docker service create --mode replicated --name my-nginx nginx
docker service create --mode global --name my-nginx nginx
# 默认是 replicated

网络模式: “PublishMode”: “ingress”

Overlay:覆盖网络 Overlay参考

ingress:特殊的Overlay网络! 具有 负载均衡 的功能! IPVS VIP !

虽然 docker 在四台机器上,实际网络是同一个! ingress 网络 ,使集群变成一个整体

image-20210912162839786

image-20210912162846252

Docker Stack

docker stack --help

docker-compose 单机部署项目!

Docker Stack部署,集群部署!

# 单机
docker-compose up -d wordpress.yaml
# 集群
docker stack deploy wordpress.yaml

# docker-compose 文件 注意deploy

Docker Secret

docker secret --help

安全! 配置密码,证书!

Docker Config

docker config --help

配置

扩展到K8S

云原生时代

Go语言! 必须掌握!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

docker学习笔记--狂神 的相关文章

随机推荐

  • GET和POST的区别,java模拟postman发post

    题解 空心正方形图案 include
  • MFC对话框中屏蔽Enter键与ESC键

    文章内容无意义 存档用 MFC对话框应用程序中 按下回车键或者ESC键 对话框会自动关闭 原因在于 当用户按下Enter键时 Windows就会自动去查找 输入焦点 落在了哪一个按钮上 获得焦点的按钮的四周将被点线矩形框所包围 如果所有按钮
  • 关于hexo的笔记 以及 常见问题

    在 Hexo 中有两份主要的配置文件 其名称都是 config yml 其中 一份位于站点根目录下 blog config yml 主要包含 Hexo 本身的配置 另一份位于主题目录下 blog themes next config yml
  • 程序员的算法课(15)-分治法获取文件中出现频次最高100词

    一 问题描述 这个问题在大数据面试中容易出现 问题如下 有一个1G大小的一个文件 里面每一行是一个词 词的大小不超过16字节 内存限制大小是1M 要求返回频数最高的100个词 二 思路 此处1G文件远远大于1M内存 分治法 先hash映射把
  • sp3585调试

    最近在调试sp3485目前已调试成功 后续把调试过程补全
  • 用Python获取链家二手房房源数据,做可视化图分析数据

    前言 数据采集的步骤是固定 发送请求 模拟浏览器对于url地址发送请求 获取数据 获取网页数据内容 gt 请求那个链接地址 返回服务器响应数据 解析数据 提取我们需要的数据内容 保存数据 保存本地文件 所需模块 win R 输入cmd 输入
  • 从计组和操作系统详解IO控制方式

    IO控制方式 实际上IO在操作系统和计组里面都有讲到 这两个内容各有侧重 又有很大的重合 这里就整理一下 操作系统里面就讲了一下基本的过程 计组还讲了各个接口电路 1 直接程序控制方式 直接程序控制方式由用户进程直接控制主存或 CPU 和外
  • ARP报文头部格式和请求流程

    文章目录 ARP头部格式 ARP请求流程 ARP头部格式 格式说明 硬件类型 16位字段 用来定义运行ARP的网络类型 每个局域网基于其类型被指派一个整数 例如 以太网的类型为1 ARP可用在任何物理网络上 协议类型 16位字段 用来定义使
  • 随记:Flutter获取widget的大小位置,状态栏高度

    也可参考 https www jianshu com p 8117fbc5b4d3 1 获取状态栏高度 MediaQueryData fromWindow WidgetsBinding instance window padding top
  • Spring Boot日志

    目录 1 日志的作用 2 自定义打印日志 3 日志级别 4 日志持久化 5 使用lombok输出日志 1 日志的作用 日志是程序的重要组成部分 其实我们几乎无时无刻都在接触日志 简单的说它其实就是程序运行过程中产生的信息 它的主要作用就是帮
  • k8s之Deployment篇

    Deployment控制器 概念 原理解读 Deployment官方文档 https kubernetes io docs concepts workloads controllers deployment Deployment概述 Dep
  • 大数据——Ubuntu配置docker的阿里云镜像加速

    Ubuntu配置docker的阿里云镜像加速 阿里云镜像加速 阿里云镜像加速 由于docker的官方的镜像源速度太慢 在国内可以通过使用阿里云或者网易云的镜像源提高下载速度 通常使用阿里云的镜像源 下面介绍怎么使用阿里云的镜像加速器 注册阿
  • python编程练习题:随机生成的各科成绩,60分以下为10-15%之间,60-90分的占70-75%之间,90分以上10%-15%之间

    d 题目 python编程练习题 随机生成的各科成绩 60分以下为10 15 之间 60 90分的占70 75 之间 90分以上10 15 之间 分析 各分数之间生成分数的概率并不是独立的 而是相互影响的 比如60分以下的占10 那么为了满
  • html纵向导航,【练习实例】HTML+CSS制作导航栏(横向与纵向)

    纵向导航栏 建立一个列表 主页 新闻 联系 关于 2 定义列表基本样式 ul 去掉列表的样式 list style type none width 200px background color DDDDDD li a 将内联元素转换为块级元
  • 安装并使用 iDRAC 服务模块

    DELL服务器 Integrated Dell Remote Access Controller 8 7 默认增加了iDRAC Service Module 但是根据官方文档 这个功能默认是没有打开 需要在服务器上安装 未安装前方法如下 1
  • linux下,用crontab定时执行scrapy任务

    之前尝试过很多方法用crontab执行scrapy的爬虫任务 但是都没出成功 总结下来有两点错误与相应的解决方法 1 手动执行时 在工程目录下输入scrapy crawl xxx就可以执行爬虫脚本了 但是用crontab时 如果直接在cro
  • 请收藏——QKL123!它能帮你挖掘项目价值(附2019年3月排行榜)

    QKL123区块链排行榜包括区块链项目 区块链交易平台 区块链媒体 区块链公众号 区块链矿机 区块链矿池 EOS Dapp ETH Dapp 区块链钱包九大榜单 相对第二期 2019年02月 榜单 该期首次新增ETH Dapp排行榜 并改进
  • 今天给大家分享一个绘图的 RGB COLOR TABLE

    如果大家觉得有用 就点个赞让更多的人看到吧
  • unity 触摸屏幕

    if Event current type EventType MouseDown 这里写鼠标按下 屏幕触摸按下 的代码 if Event current type EventType MouseDrag 这里写鼠标拖动 屏幕触摸滑动 的代
  • docker学习笔记--狂神

    Docker入门 Docker能做什么 虚拟机技术 虚拟机技术缺点 资源占用十分多 冗余步骤多 启动很慢 容器化技术 容器化技术不是模拟的一个完整的操作系统 比较Docker 和 虚拟机技术不用 传统虚拟机 虚拟出一条硬件 运行一个完整的操