狂神说
使用Oracle VM VirtualBox 进行学习,linux:Ubuntu,后期使用CentOS7
官网: https://www.docker.com/

01 Docker概述

Docker为什么出现

  1. 原因:环境配置不能跨平台

  2. 方案

    传统方式:jar(开发人员)+ 部署(运维人员)

    解决方式:开发打包上线一套流程

  3. Docker的思想来源于集装箱

    1. JRE — 多个应用(容易引起端口冲突/配置错误/连接错误)— 原来是交叉应用的
    2. 隔离:Docker核心思想,打集装箱,每个箱子都是互相隔离
  4. Docker通过隔离机制可以将服务器利用到极致

Docker历史

  1. Docker:容器化技术,
  2. 也是一种虚拟化技术,相对于虚拟机较为轻巧,
  3. 最核心的环境只有几兆,可以在这个基础上添加jdk和mysql环境,
  4. 运行的时候运行镜像就可以

Docker是基于Go语言开发的一个开源项目

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

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

Docker能做什么

虚拟机

虚拟机技术缺点

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

容器化技术

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

Docker 和 虚拟机技术 的不同

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

DevOps(开发+运维)

四个特点:
应用更快速的交付和部署

  1. 传统:一堆帮助文档,安装程序
  2. Docker:打包镜像 发布测试 一键运行

更快捷的升级和扩缩容

  1. 使用了Docker之后,部署应用就像搭积木一样
  2. 将项目打包为一个镜像(带着环境,可以直接运行),水平扩展 服务器A;服务器B(当服务器A遇到问题需要用负载均衡解决的时候可以在服务器B上直接运行镜像,这样就可以实现扩展)

更简单的系统运维
​ 容器化之后,开发、测试环境都是高度一致的

更高效的计算资源利用
​ Docker是内核级别的虚拟化,可以在一个物理机上运行很多容器实例,服务器的性能可以被压榨到极致

02 Docker安装

Docker的基本组成

镜像(image)

Docker镜像好比是一个模板,可以通过这个模板来创建容器服务

tomcat镜像 =》run =》tomcat01容器(提供服务器)

容器(container)

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

基本命令:启动 停止 删除

目前可以将这个容器理解为一个简易的Linux系统

仓库(repository)

仓库是存放镜像的地方

仓库分为共有仓库和私有仓库

Docker Hub(默认是国外的)

阿里云,华为云等都有容器服务器(配置镜像加速)

安装

ubuntu

我的环境(换成centos了,教程在ubuntu后面):Oracle VM VirtualBox 虚拟机版本:Ubuntu 18.04??

  1. 卸载已经安装的版本:

    1. 命令:sudo apt-get remove docker docker-engine docker.io containerd runc
    2. 如果没有安装过,会报如下信息
  2. 设置仓库

    1. 更新apt包索引:

      sudo apt-get update

    2. 安装apt依赖包,用于通过HTTPS来获取仓库

   sudo apt-get install \apt-transport-https \ca-certificates \curl \gnupg \lsb-release
  1. 添加gpc秘钥
  curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
  1. 使用aliyun镜像
echo \"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] http://mirrors.aliyun.com/docker-ce/linux/ubuntu/ \$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
  1. 安装Docker引擎
sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io
  1. 启动Docker systemctl start docker

  2. 查看版本(是否安装成功) sudo docker version

  3. 测试运行
    sudo docker run hello-world

  4. 查看hello-world镜像 sudo docker images

  5. 了解:卸载

    1. 卸载依赖
    2. 删除资源

CentOS

Oracle VM VirtualBox 虚拟机版本:CentOS-7

  1. 卸载已经安装的版本

sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine
  1. 设置存储库

      # 安装yum-utils包yum install -y yum-utils# 设置镜像仓库# 官方(不推荐,太慢)sudo yum-config-manager \--add-repo \https://download.docker.com/linux/centos/docker-ce.repo# 国内镜像(阿里云)yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    
  2. 安装Docker引擎

    1. 安装最新版本的 Docker Engine 和 containerd,或者进入下一步安装特定版本:
      # 安装最新Dockersudo yum install docker-ce docker-ce-cli containerd.io
    
  3. 更新yum软件包索引 yum makecache fast

  4. 安装Docker相关的

    1. docker-ce:社区版 ee:企业版

      # 安装最新版本yum install docker-ce docker-ce-cli containerd.io# 也可指定版本进行安装
    

之后的步骤参考ubuntu

docker的默认工作路径:/var/lib/docker ;查看的时候需要权限sudo

配置阿里云镜像加速


回顾HelloWorld流程

底层原理

Docker是怎么工作的

  1. Docker是一个Client-Server结构的系统,Docker的守护进程运行在主机上,通过Socket从客户端访问
  2. Docker-Server接收到Docker-Client的指令,就会执行这个命令

Docker为什么比VM快?

  1. Docker有着比虚拟机更少的抽象层
  2. Docker利用的是宿主机的内核,VM需要的是Guest OS

所以新建一个容器的时候,docker不需要虚拟机一样重新加载一个操作系统的内核,避免引导。

虚拟机是加载Guest OS,是分钟级别的;Docker是利用宿主机的操作系统,省略了这个复杂的过程,是秒级的

03 Docker的常用命令

帮助命令

docker version   # 显示Docker版本信息
docker info         # 显示Docker的系统信息,包括镜像和容器的数量
docker --help       # 帮助命令

帮助文档:https://docs.docker.com/engine/reference/commandline/

镜像命令

docker images

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

解释:

# 解释
REPOSITORY          # 镜像的仓库源
TAG                 # 镜像的标签
IMAGE ID            # 镜像的id
CREATED             # 镜像的创建时间
SIZE                # 镜像的大小# 可选项
-a,--all            # 列出所有镜像
-q,--quiet          # 只显示镜像的id# 测试运行:
lixiaolu@lixiaolu-VirtualBox:~$ sudo docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
hello-world   latest    d1165f221234   2 months ago   13.3kB
lixiaolu@lixiaolu-VirtualBox:~$ sudo docker images -a
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
hello-world   latest    d1165f221234   2 months ago   13.3kB
lixiaolu@lixiaolu-VirtualBox:~$ sudo docker images -q
d1165f221234

docker search

搜索镜像

# 可执行命令
lixiaolu@lixiaolu-VirtualBox:~$ sudo docker search --helpUsage:  docker search [OPTIONS] TERMSearch the Docker Hub for imagesOptions:-f, --filter filter   Filter output based on conditions provided--format string   Pretty-print search using a Go template--limit int       Max number of search results (default 25)--no-trunc        Don't truncate output# 可选项,通过收藏来过滤;搜索收藏超过4000的
lixiaolu@lixiaolu-VirtualBox:~$ sudo docker search mysql --filter=stars=4000
NAME      DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql     MySQL is a widely used, open-source relation…   10944     [OK]
mariadb   MariaDB Server is a high performing open sou…   4137      [OK]

docker pull

下载镜像

# 可执行命令
lixiaolu@lixiaolu-VirtualBox:~$ docker pull --helpUsage:  docker pull [OPTIONS] NAME[:TAG|@DIGEST]Pull an image or a repository from a registryOptions:-a, --all-tags                Download all tagged images in the repository--disable-content-trust   Skip image verification (default true)--platform string         Set platform if server is multi-platform capable-q, --quiet                   Suppress verbose output# 下载镜像,docker pull 镜像名[:tag]
# 下载mysql,不写tag的时候默认下载的是最新版
lixiaolu@lixiaolu-VirtualBox:~$ sudo docker pull mysql
Using default tag: latest  # 不写tag,默认最新版
latest: Pulling from library/mysql
69692152171a: Pull complete # 分层下载,docker images 的核心,联合文件系统
1651b0be3df3: Pull complete
951da7386bc8: Pull complete
0f86c95aa242: Pull complete
37ba2d8bd4fe: Pull complete
6d278bb05e94: Pull complete
497efbd93a3e: Pull complete
f7fddf10c2c2: Pull complete
16415d159dfb: Pull complete
0e530ffc6b73: Pull complete
b0a4a1a77178: Pull complete
cd90f92aa9ef: Pull complete
Digest: sha256:d50098d7fcb25b1fcb24e2d3247cae3fc55815d64fec640dc395840f8fa80969
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest# 等价于
sudo docker pull mysql
sudo docker pull docker.io/library/mysql:latest
# 指定版本下载,所指定的版本需要在docker官网也能找到


查看安装结果

docker rmi

删除镜像(rm image)

删除的时候可以通过镜像的id或者name来删除

sudo docker rmi -f [imageId]        # -f表示强制删除(force)
sudo docker rmi -f [imageName]      # -f表示强制删除(force)
sudo docker rmi -f [imageId] [imageId] # 删除多个镜像sudo docker rmi 2c9028880e58     # 删除5.7版本的MySQL
sudo docker rmi -f $(sudo docker images -aq)    # 删除所有镜像 sudo docker images -aq表示查出所有镜像id(注意权限问题)

容器命令

有了镜像才可以创建容器,现在在虚拟机下使用docker下载一个centos镜像 docker pull centos

# 启动镜像
docker run [可选参数] image# 参数说明
--name="[NANE]"          # 容器名字
-d                      # 后台方式运行
-it                     # 使用交互方式运行,进入容器查看内容
-p                      # (小写p)指定容器的端口 -p 8080:8080-p ip:主机端口:容器端口-p 主机端口:容器端口-p 容器端口容器端口
-P                      # (大写P)随机指定端口# 查看运行中的容器
docker ps# docker ps命令# 列出正在运行的容器
-a      # 列出当前正在运行的容器+带出历史运行过的容器
-n ?    # 显示最近创建的?个容器
-q      # 只显示容器的编号# 退出容器
exit    # 直接停止容器并退出
(ctrl+p) + (ctrl+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]      # 强制停止当前容器,当正常stop报错的时候,可以使用这个命令
# 测试
# 启动镜像
docker run -it ubuntu /bin/bash # 运行后会进入docker中的ubuntu容器root@lixiaolu-VirtualBox:/home/lixiaolu# docker run -it ubuntu /bin/bashroot@af5805d3c734:/# ls      进入容器
bin   dev  home  lib32  libx32  mnt  proc  run   srv  tmp  var
boot  etc  lib   lib64  media   opt  root  sbin  sys  usr# 从容器中退回主机 (查看正在运行的容器的时候不会显示这个,因为已经退出了)
exitdocker ps    # 查看正在运行的容器,由于已经退出,所以并不在运行列表
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMESdocker ps -a # 查看曾经运行的容器
CONTAINER ID   IMAGE          COMMAND       CREATED          STATUS                      PORTS     NAMES
af5805d3c734   ubuntu         "/bin/bash"   5 minutes ago    Exited (0) 15 seconds ago             practical_engelbart
90f7bf65d193   ubuntu         "/bin/bash"   5 minutes ago    Exited (0) 5 minutes ago              stupefied_davinci
35fe86bf7e73   d1165f221234   "/hello"      37 minutes ago   Exited (0) 37 minutes ago             elastic_pascal
21f199c76de6   d1165f221234   "/hello"      37 minutes ago   Exited (0) 37 minutes ago             epic_hertz
96ae1378194a   d1165f221234   "/hello"      22 hours ago     Exited (0) 22 hours ago               xenodochial_carson
7a6d8766b878   d1165f221234   "/hello"      23 hours ago     Exited (0) 23 hours ago               tender_ellis
a88af85a2739   d1165f221234   "/hello"      23 hours ago     Exited (0) 23 hours ago               practical_brown

其他

后台启动容器

# 命令 docker run -d 镜像名docker run -d ubuntu# 问题:使用docker ps之后发现ubuntu停止了
# 常见坑:若docker容器使用后台运行,则必须要有一个前台进程,docker发现没有应用,就会自动停止
# 如果装了Nginx,容器启动后,发现自己没有提供服务,就会立即停止,就是没有程序了

查看日志

docker logs -f -t --tail [容器id]# 如果没有日志,可以自己编写一段shell脚本
docker run -d ubuntu /bin/bash -c "while true;do echo lxl;sleep 1;done"
# 再次查看的时候
docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS     NAME
S27f9c2dc0e69   ubuntu    "/bin/bash -c 'while…"   5 seconds ago    Up 4 seconds              blissful_mestorf566fd24f8905   ubuntu    "/bin/bash"              12 minutes ago   Up 12 minutes             peaceful_babbage
# 查看日志docker logs -f -t --tail 20 27f9c2dc0e69# 会先出20条,然后接着往后打印日志

查看容器中进程信息ps

docker top [容器id]# docker top 27f9c2dc0e69UID                 PID                 PPID                C                   STIME     root                8551                8514                0                   17:16root                9452                8551                0                   17:29    # UID:用户ID# PID:进程ID# PPID:父进程ID

查看镜像的元数据

docker inspect [容器id]

docker inspect 27f9c2dc0e69
# 运行结果:
[{"Id": "27f9c2dc0e69b49529ac5238798cb17e3e8eccc8fb4c67e35c475db78b2b95b0","Created": "2021-06-03T09:16:37.861735346Z","Path": "/bin/bash","Args": ["-c","while true;do echo lxl;sleep 1;done"],"State": {"Status": "running","Running": true,"Paused": false,"Restarting": false,"OOMKilled": false,"Dead": false,"Pid": 8551,"ExitCode": 0,"Error": "","StartedAt": "2021-06-03T09:16:38.617115427Z","FinishedAt": "0001-01-01T00:00:00Z"},"Image": "sha256:7e0aa2d69a153215c790488ed1fcec162015e973e49962d438e18249d16fa9bd","ResolvConfPath": "/var/lib/docker/containers/27f9c2dc0e69b49529ac5238798cb17e3e8eccc8fb4c67e35c475db78b2b95b0/resolv.conf","HostnamePath": "/var/lib/docker/containers/27f9c2dc0e69b49529ac5238798cb17e3e8eccc8fb4c67e35c475db78b2b95b0/hostname","HostsPath": "/var/lib/docker/containers/27f9c2dc0e69b49529ac5238798cb17e3e8eccc8fb4c67e35c475db78b2b95b0/hosts","LogPath": "/var/lib/docker/containers/27f9c2dc0e69b49529ac5238798cb17e3e8eccc8fb4c67e35c475db78b2b95b0/27f9c2dc0e69b49529ac5238798cb17e3e8eccc8fb4c67e35c475db78b2b95b0-json.log","Name": "/blissful_mestorf","RestartCount": 0,"Driver": "overlay2","Platform": "linux","MountLabel": "","ProcessLabel": "","AppArmorProfile": "docker-default","ExecIDs": null,"HostConfig": {"Binds": null,"ContainerIDFile": "","LogConfig": {"Type": "json-file","Config": {}},"NetworkMode": "default","PortBindings": {},"RestartPolicy": {"Name": "no","MaximumRetryCount": 0},"AutoRemove": false,"VolumeDriver": "","VolumesFrom": null,"CapAdd": null,"CapDrop": null,"CgroupnsMode": "host","Dns": [],"DnsOptions": [],"DnsSearch": [],"ExtraHosts": null,"GroupAdd": null,"IpcMode": "private","Cgroup": "","Links": null,"OomScoreAdj": 0,"PidMode": "","Privileged": false,"PublishAllPorts": false,"ReadonlyRootfs": false,"SecurityOpt": null,"UTSMode": "","UsernsMode": "","ShmSize": 67108864,"Runtime": "runc","ConsoleSize": [0,0],"Isolation": "","CpuShares": 0,"Memory": 0,"NanoCpus": 0,"CgroupParent": "","BlkioWeight": 0,"BlkioWeightDevice": [],"BlkioDeviceReadBps": null,"BlkioDeviceWriteBps": null,"BlkioDeviceReadIOps": null,"BlkioDeviceWriteIOps": null,"CpuPeriod": 0,"CpuQuota": 0,"CpuRealtimePeriod": 0,"CpuRealtimeRuntime": 0,"CpusetCpus": "","CpusetMems": "","Devices": [],"DeviceCgroupRules": null,"DeviceRequests": null,"KernelMemory": 0,"KernelMemoryTCP": 0,"MemoryReservation": 0,"MemorySwap": 0,"MemorySwappiness": null,"OomKillDisable": false,"PidsLimit": null,"Ulimits": null,"CpuCount": 0,"CpuPercent": 0,"IOMaximumIOps": 0,"IOMaximumBandwidth": 0,"MaskedPaths": ["/proc/asound","/proc/acpi","/proc/kcore","/proc/keys","/proc/latency_stats","/proc/timer_list","/proc/timer_stats","/proc/sched_debug","/proc/scsi","/sys/firmware"],"ReadonlyPaths": ["/proc/bus","/proc/fs","/proc/irq","/proc/sys","/proc/sysrq-trigger"]},"GraphDriver": {"Data": {"LowerDir": "/var/lib/docker/overlay2/159275e02c9c12f8ee3bbda8d79ba0bf4211d5290298a89d7eadab01b2ecdb7c-init/diff:/var/lib/docker/overlay2/0d62b2366981a626370d43ec7c59a01fa99e33f0302a56d2d643a97e22840906/diff:/var/lib/docker/overlay2/b51ad877af70eb99fe7f1777b916a8b873070e7d58b753daaeb0ff830a4fe9b1/diff:/var/lib/docker/overlay2/7d928819ea5e4b1d1ee7b39146acc51f06bfdcdde9f66a5ca1d27b4c1a5661c8/diff","MergedDir": "/var/lib/docker/overlay2/159275e02c9c12f8ee3bbda8d79ba0bf4211d5290298a89d7eadab01b2ecdb7c/merged","UpperDir": "/var/lib/docker/overlay2/159275e02c9c12f8ee3bbda8d79ba0bf4211d5290298a89d7eadab01b2ecdb7c/diff","WorkDir": "/var/lib/docker/overlay2/159275e02c9c12f8ee3bbda8d79ba0bf4211d5290298a89d7eadab01b2ecdb7c/work"},"Name": "overlay2"},"Mounts": [],"Config": {"Hostname": "27f9c2dc0e69","Domainname": "","User": "","AttachStdin": false,"AttachStdout": false,"AttachStderr": false,"Tty": false,"OpenStdin": false,"StdinOnce": false,"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd": ["/bin/bash","-c","while true;do echo lxl;sleep 1;done"],"Image": "ubuntu","Volumes": null,"WorkingDir": "","Entrypoint": null,"OnBuild": null,"Labels": {}},"NetworkSettings": {"Bridge": "","SandboxID": "4a26baa40decaac8c7705a8332b6b8e1912aca682b6e331cd31f8ab394667805","HairpinMode": false,"LinkLocalIPv6Address": "","LinkLocalIPv6PrefixLen": 0,"Ports": {},"SandboxKey": "/var/run/docker/netns/4a26baa40dec","SecondaryIPAddresses": null,"SecondaryIPv6Addresses": null,"EndpointID": "6b9dff60a69acb594e7bb64fad367258e9d67bb1a1497ee85fa9e46ab31216c6","Gateway": "172.17.0.1","GlobalIPv6Address": "","GlobalIPv6PrefixLen": 0,"IPAddress": "172.17.0.3","IPPrefixLen": 16,"IPv6Gateway": "","MacAddress": "02:42:ac:11:00:03","Networks": {"bridge": {"IPAMConfig": null,"Links": null,"Aliases": null,"NetworkID": "c0c65d41628b363a565b17e46b027e1d0372cc728277678d3a4042665b517f06","EndpointID": "6b9dff60a69acb594e7bb64fad367258e9d67bb1a1497ee85fa9e46ab31216c6","Gateway": "172.17.0.1","IPAddress": "172.17.0.3","IPPrefixLen": 16,"IPv6Gateway": "","GlobalIPv6Address": "","GlobalIPv6PrefixLen": 0,"MacAddress": "02:42:ac:11:00:03","DriverOpts": null}}}}
]

进入当前正在运行的容器

# 通常容器都是使用后台方式运行的,需要进入容器,修改一些配置
# 命令docker exec -it [容器id] /bin/bashdocker attach [容器id]
# 两种命令比较exec:进入容器后开启一个新的终端,可以在里面操作(常用)attach:进入容器中正在执行的终端,不会启动新的进程

从容器内拷贝到主机上

docker cp 容器id:容器内文件路径 目的文件路径
docker cp [容器id]:/home/test.java /home

拷贝是一个手动过程,未来可以使用 -v 卷(volumn)技术实现目录自动同步

小结

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

作业练习

安装Nginx

# 1. 搜索镜像 search;建议去docker官网搜索,可以看到相应的帮助文档信息
# 2. 下载镜像 pull
# 3. 运行测试
# -d 后台运行
# --name 给容器命名
# -p 宿主机端口,容器内部端口


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

部署tomcat

# 1. 官方的使用
docker run -it --rm tomcat:9.0
# 我们之前的启动都是后台,停止了容器之后,容器还是可以查到
# docker run -it --rm 一般用来测试用完就删除# 2. 下载再启动
docker pull tomcat
# 启动运行
docker run -d -p 3355:8080 --name tomcat01 tomcat
# 访问3355的时候如果显示404,则是因为tomcat不全,说明测试是没有问题的# 进入容器
docker exec -it tomcat01 /bin/bash# 发现问题:1. linux命令少了   2. 没有webapps 是阿里云镜像的原因,默认是最小的镜像,所以不必要的都剔除掉 (保证最小可运行的环境!!!)

webapps.dist下的root文件如果放到webapps下就可以在网页中看到效果

思考:我们以后部署项目,如果每次都进入容器是十分麻烦的,要是可以在容器外部提供一个映射路径如webapps,在外部放置项目,自动同步内容就好了

部署ES+Kibana

什么是es kibana

ES:Elasticsearch6搜索引擎,Kibana是它的可视化操作界面

ES:全文检索
  1. Elasticsearch是一个基于Lucene的搜索服务器,它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。
  2. Elasticsearch是用java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业搜索引擎。
  3. ES用于云计算中,能够达到实时搜索、稳定、可靠、快速、安装使用方便
  4. 客户端安装在java、.NET(C#)、PHP、Python、Apache Groovy、Ruby和其他语言中都是可用的
  5. docker中的文档位置:https://hub.docker.com/_/elasticsearch
Kibana
  1. Kibana是一个开源的分析与可视化平台,设计出来用于和ES一起使用
  2. 可以使用Kibana搜索,查看存放在ES中的数据。Kibana与ES的交互方式是各种不同的图表、表格、地图等直观的展示数据,从而达到高级的数据分析和可视化的目的
  3. ELK技术栈:ES、Logstash、Kibana。
    1. 这三个技术的组合是大数据领域中一个很巧妙的设计,是一种典型的MVC思想,模型持久层、视图层、和控制器层。
    2. Logstash担任控制层的角色,负责搜集和 过滤数据;ES担任数据持久层的角色,负责存储数据;Kibana担任视图层角色,拥有各种维度的查询和分析,并使用图形化的界面展示存放在ES中的数据
    3. docker中的文档位置:https://hub.docker.com/_/kibana

部署

# es 暴露的端口很多
# es 十分耗内存
# es 的数据一般需要防止到安全目录!挂载# --net somenetwork:网络配置(暂时用不到)
# -p 9200:9200 -p 9300:9300:暴露的端口
# -e "discovery.type=single-node" :集群
docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:tag# 启动es
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2# 启动了es之后linux就卡住了  可使用docker stats查看cpu的状态
# es是十分耗内存的,启动的时候会占用约两个G的内存
# 解决卡顿方式:停止整个docker(不建议)
# 当测试es安装成功后,立刻关闭,然后增加内存的限制
docker run -d --name elasticsearch02 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2
# 查看docker stats [容器id]

思考:如何使用Kibana连接es?网络如何连接?

可视化

  • portainer(不是最佳选择,先用着)
# -p 8088:9000 内网访问:9000;外网访问:8088
# -v /var/run/docker.sock 挂载
# --privileged=true 授权可访问
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock --privileged=true portainer/portainer
  • Rancher(持续集成(CI)/持续部署(CD) 的时候用)
  • 浏览器访问:

04 Docker镜像讲解

镜像是什么

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

所有的应用,直接打包成为一个docker镜像,就可以直接跑起来

如何得到镜像

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

Docker镜像加载原理

UnionFS(联合文件系统)

下载时候的分层下载就是这个

  1. Union文件系统是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。
  2. UnionFS是Docker镜像的基础。
  3. 镜像可以通过分层来继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像
  4. 特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

Docker镜像加速原理

  1. Docker镜像实际上是由一层一层

  2. bootFS(boot file system)

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

底下的层是共用的

平时安装进虚拟机的CentOS都是好几个G

对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令、工具和程序即可,因为底层直接用Host的Kernel,自己只需要提供rootfs就可以了。由此可见对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs。

虚拟机是分钟级别的,

分层理解

以拉取redis为例

拉取:

查看镜像元数据(inspect):

分层信息:


理解:

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

如下图:基于ubuntu Linux 16.04 创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加python包,该镜像当前包含3个镜像层。如下图(好比windows中的安全补丁)

在添加额外镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点很重要,下图中举了一个简单的例子,每个镜像层包含3个镜像,而镜像包含了来自两个镜像层的6个文件

上图的镜像层跟之前图中的略有区别,主要目的是便于展示文件。

下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,是因为最上层的文件7是文件5的一个更新版本

这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件,这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。

Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。

Linux上可用的存储引擎有AUFS、OverLay2、Driver Mapper、Btrfs及ZFS。每种存储引擎都技术Linux中对应的文件系统或者块设备技术,且都有其独特的特点。

Docker在Windows上仅支持windowsfilter一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW[1]。

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

分层的好处:下载的时候分层下载,当遇到和其他应用相同的层的时候可以直接复用已经存在的

特点

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

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

commit镜像

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

启动tomcat后发现,webapps下是空的,webapps.dist有运行tomcat所需要的文件。

将webapps.dist下的文件复制到webapps下之后,进行一次镜像的提交。

docker commit -a="aimer" -m="add for webapps" 815da7a018c3 tomcat01:1.0docker commit -a="[作者信息]" -m="[提交信息] [镜像名称]:[镜像版本号]

提交成功之后,查看一下镜像

tomcat01即提交的镜像,并没有将原来的镜像覆盖,而是新建了一个镜像。

05 容器数据卷

什么是容器数据卷

docker的理念回顾
将应用和环境打包成一个镜像

关于数据,如果数据在容器中,那么将容器删除的时候,数据就会丢失。需求:数据可以持久化

以MySQL为例:希望MySQL数据可存储在本地

实现:容器之间有一个数据共享的技术,Docker容器中产生的数据可以同步到本地

卷技术,目录的挂载,将容器内的目录挂载到虚拟机(或linux)上

总结:为什么要用卷技术?为了容器持久化和同步操作,容器间也是可以数据共享的

使用数据卷(双向绑定)

方式一:直接使用命令挂载 -v

docker run -it -v 主机目录:容器内目录  # ":"前后不能有空格
docker run -it -v /home/ceshi:/home centos /bin/bash
# 在home中存放的内容会自动同步到/home/ceshi下

# 查看是否挂载成功
docker inspect [容器id??]
docker inspect ff174bf554b0# 部分运行日志"Mounts": [{"Type": "bind","Source": "/home/ceshi", # 源地址 (主机地址)"Destination": "/home",   # 目标地址 (docker地址)"Mode": "","RW": true,"Propagation": "rprivate"}],

挂载成功之后,不论是在主机下的/home/ceshi下操作,还是在docker中的/home下操作,另一个目录都会自动同步;但是当把镜像删除之后,挂载的数据卷内容还是存在的

若退出容器,在外面进行操作,容器内也会自动同步(这样就省去了进入容器的麻烦)

1. 停止容器
2. 在宿主机上修改文件
3. 启动容器
4. 容器内的数据依旧是同步的

实战:安装MySQL

思考:MySQL的数据持久化问题

# 获取镜像
docker pull mysql:5.7# 运行容器,需要数据挂载 注意:安装启动mysql的时候需要配置密码
-d 后台运行
-p 端口映射
-v 卷挂载
-e 环境配置
--name 容器名字
docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=000000 --name mysql01 mysql:5.7# 启动成功之后,可以在本地使用sqlyod连接测试
# sqlyod连接到服务器的3310端口,3310和容器内3306映射,这样就可以连上了
# 在本地测试创建一个数据库,查看映射路径是否映射成功

具名和匿名挂载

# 匿名挂载
-v [容器内路径] (不写主机内目录,会自动生成一个目录)
docker run -d -P --name nginx01 -v /etc/nginx nginx# 查看所有volume卷的情况
docker volume ls
# 只写了容器中的路径,而没有写容器外的路径

# 具名挂载
-v [卷名]:[容器内路径]
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
# juming-nginx:/etc/nginx nginx 这里指定了卷名# 查看volume
docker volume ls

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

进入/var/lib/docker/volumes/xxx/_data目录


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

# 如何确定是具名挂载还是匿名挂载:是否指定路径挂载
-v [容器内路径]              # 匿名挂载
-v [卷名]:[容器内路径]        # 具名挂载
-v /[宿主机路径]:[容器内路径]  # 指定路径挂载

扩展:

# 通过 -v 容器内路径:ro rw 改变读写权限
ro read-only  # 只读
rw read-write # 可读可写# 一旦这个设置了容器权限,容器对我们挂载出来的内容就有限定了
docker run -d -P --name nginx03 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx03 -v juming-nginx:/etc/nginx:rw nginx# ro: 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作的

初识DockerFile

DockerFile就是用来构建docker镜像的构建文件,命令脚本

通过脚本生成镜像,镜像是一层一层的,所对应的脚本就是一层一层的命令,每个命令都是一层镜像

方式二:

# 自己写的脚本
# 创建一个dockerFile文件,名字可以随便,但是建议是dockerFile
# 文件中的内容  指令(建议大写) 参数
FROM centos      # 指定参数VOLUME ["/home/docker-test-volume/volume01","/home/docker-test-volume/volume02"] # 注意“VOLUME”和中括号之间的空格路径要写绝对路径CMD echo "---end---"
CMD /bin/bash
# 这里每个命令就是镜像的一层# 生成命令
docker build -f dockerfile1 -t lxl_centos:1.0 .

# 启动下自己写的容器
docker run -it [容器id] /bin/bash
# 可能有error

VOLUME ["/home/docker-test-volume/volume01","/home/docker-test-volume/volume02"]写成VOLUME ["volume01","volume02"],会报错,因为不是绝对路径

报错信息:

docker: Error response from daemon: OCI runtime create failed: invalid mount {Destination:volume01 Type:bind Source:/var/lib/docker/volumes/95eb83c4d838517c2c909cbfe53ff0d3a254b271c6395d00820ccb0bc5947af6/_data Options:[rbind]}: mount destination volume01 not absolute: unknown.

再启一次:还是报错

docker: Error response from daemon: OCI runtime create failed: invalid mount {Destination:home/docker-test-volume/volume01 Type:bind Source:/var/lib/docker/volumes/143e5e92fe74b95a072fd5a44c89cdd51b40ddfa0c087e0fc331f452a37f0a66/_data Options:[rbind]}: mount destination home/docker-test-volume/volume01 not absolute: unknown.

正常启动:

查看挂载的信息:

home/docker-test-volume/目录即为生成镜像的时候自动挂载的数据卷目录,此卷目录一定在外部有同步的目录,使用docker inspect 查看元数据后可找到映射的目录

这种方式为匿名挂载

在容器中创建一个文件:

在对应的外部路径下/var/lib/docker/volumes/c7e3fb47f4ea07c52ce61ef187eb7b1f4ce1bd4a66aa7987472da067b2801f0b/_data可找到:

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

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

数据卷容器

如多个MySQL同步数据

# 现在启动两个容器,让它们来同步数据
# 第一个
docker run -it --name lxl01 63ad41b0da3d /bin/bash
# 第二个
# --volumes-from lxl01  相当于继承了lxl01的挂载信息
# 此处的centos01就相当于数据卷容器
docker run -it --name lxl02 --volumes-from lxl01 63ad41b0da3d

测试是否同步

  1. 在lxl01的volume01中新建文件

  2. 在lxl02查看是否同步

  3. 在lxl02的volume01中新建文件

  4. 在lxl01查看是否同步

  5. 结果都是可以同步的

  6. 新创建一个容器lxl03,可看到在volume01中也是同步了lxl01和lxl02的信息

  7. 查看本地是否存在挂载的信息

  8. 同理可测试volume02的同步情况(注:volume01和volume02的挂载目录不同)

–volumes-from 可实现容器间的数据共享,上面的例子中lxl01、lxl02、lxl03这三个容器都是数据共享的

下面再来测试,停掉或删除容器之后数据是否存在

  1. 停掉lxl01(未删除容器)

  2. 在lxl02中查看,lxl01_1.txt仍存在

  3. 现删除容器lxl01

  4. 查看信息是否仍存在:仍存在lxl01_1.txt

现在在lxl02和lxl03上操作,看看是否会继续同步

  1. 在lxl02的volume01中新建文件lxl02_2.txt

  2. 在lxl03查看是否仍然同步

  3. 仍然同步

数据卷机制,拷贝,删掉一个不会影响别的

数据卷应用

​ 多个MySQL实现数据共享

docker run -d - p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
# 再起一个 【注意端口号】
docker run -d - p 3311:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7

结论

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

但是一旦持久化到了本地,本地的数据是不会删除的

06 DockerFile

DockerFile介绍

dockerFile是用来构建Docker镜像的文件,是命令参数脚本

构建步骤:

  1. 编写dockerfile文件
  2. docker build 构建成为一个镜像
  3. docker run运行镜像
  4. docker push 发布镜像(可发送到两个位置)
    1. DockerHub,可供他人使用
    2. 阿里云镜像仓库

发布到hub


点进去之后就是镜像位置,会跳转到gitHub


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

DockerFile的构建过程

脚本的编写!!

  1. 指令的大小写:DockerFile的指令是忽略大小写的,但建议使用大写
  2. 指令的执行顺序是从上到下的
  3. #表示注释
  4. 每一个指令都会创建一个新的镜像层,并提交

DockerFile是面向开发的,以后发布项目,创建镜像,都需要编写DockerFile文件

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

步骤:开发 部署 上线运维…缺一不可

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

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

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

DockerFile的指令

使用这些命令可构建自己的镜像

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


实战测试

centos测试

  1. 编写DockerFile的文件
   FROM centosMAINTAINER ayuan<3610089198@qq.com>ENV MYPATH /usr/localWORKDIR $MYPATH RUN yum -y install vimRUN yum -y install net-toolsEXPOSE 80 CMD echo $MYPATHCMD echo "---end---"CMD /bin/bash
  1. 编译运行,通过这个文件构建镜像
   # 运行成功的部分信息Successfully built 55313e0af22eSuccessfully tagged mycentos:1.0
  1. 运行测试
   [root@localhost dockerfile]# docker run -it mycentos:1.0 [root@0a77b114ce96 local]# pwd/usr/local                       # dockerfile中编写的MYPATH# 比较一下原版centos[root@bogon ~]# docker run -it centos[root@48b2f248c7ce /]# pwd/                              # 启动之后默认是在根目录
  1. 使用ifconfig测试
   [root@0a77b114ce96 local]# ifconfigeth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)RX packets 8  bytes 656 (656.0 B)RX errors 0  dropped 0  overruns 0  frame 0TX packets 0  bytes 0 (0.0 B)TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536inet 127.0.0.1  netmask 255.0.0.0loop  txqueuelen 1000  (Local Loopback)RX packets 0  bytes 0 (0.0 B)RX errors 0  dropped 0  overruns 0  frame 0TX packets 0  bytes 0 (0.0 B)TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

  1. 测试 vim
[root@0a77b114ce96 local]# vim test

cat test

注:mydockerfile-centos文件中写了多个CMD,只有最后一个会生效,所以当使用命令docker run mycentos:1.0的时候,并不会有内容输出.

新建一个mydockerfile-centos2,内容如下

FROM centos
MAINTAINER ayuan<3610089198@qq.com>ENV MYPATH /usr/local2
WORKDIR $MYPATHRUN yum -y install vim
RUN yum -y install net-toolsEXPOSE 81CMD echo "now u see me"

并使用其创建的镜像为 mycentos:1.1

此时再使用docker run mycentos:1.1的时候会有内容输出

[root@bogon dockerfile]# docker run mycentos:1.1
now u see me

查看镜像构建历史

[root@bogon ~]# docker history b4d1f561551c
IMAGE          CREATED        CREATED BY                                      SIZE      COMMENT
b4d1f561551c   20 hours ago   /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B
ec25d74b54d8   20 hours ago   /bin/sh -c #(nop)  EXPOSE 81                    0B
a15cf7014ac8   20 hours ago   /bin/sh -c yum -y install net-tools             24.9MB
fc3ebb2dce60   20 hours ago   /bin/sh -c yum -y install vim                   60.7MB
148148e015b4   20 hours ago   /bin/sh -c #(nop) WORKDIR /usr/local2           0B
5894cd6588ba   20 hours ago   /bin/sh -c #(nop)  ENV MYPATH=/usr/local2       0B
d000efa750f3   20 hours ago   /bin/sh -c #(nop)  MAINTAINER ayuan<36100891…   0B
300e315adb2f   6 months ago   /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>      6 months ago   /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B
<missing>      6 months ago   /bin/sh -c #(nop) ADD file:bd7a2aed6ede423b7…   209MB

CMD和ENTRYPOINT区别

CMD["[命令1]","[命令2]",…]:执行多条命令,用“,”分割,表示运行之后自动执行的命令

  1. 测试CMD
 1. 编写dockerfile-cmd-test文件[root@bogon dockerfile]# cat dockerfile-cmd-test FROM centosCMD ["ls","-a"]2. 构建镜像docker build -f dockerfile-cmd-test -t cmdtest .3. 运行之后会自动执行 ls -a 命令[root@bogon dockerfile]# docker run cmdtest....dockerenvbindevetchomeliblib64lost+foundmediamntoptprocrootrunsbinsrvsystmpusrvar4. 尝试为CMD增加参数 意使其执行 ls -al[root@bogon dockerfile]# docker run cmdtest -ldocker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.# 结果会报错,因为在CMD的情况下,-l会取代 ls -a ,但是-l不是完整的命令,所以会报错# 改正,ls -al 是完整的命令,会执行[root@bogon dockerfile]# docker run cmdtest ls -altotal 0drwxr-xr-x.   1 root root   6 Jun 25 03:20 .drwxr-xr-x.   1 root root   6 Jun 25 03:20 ..-rwxr-xr-x.   1 root root   0 Jun 25 03:20 .dockerenvlrwxrwxrwx.   1 root root   7 Nov  3  2020 bin -> usr/bindrwxr-xr-x.   5 root root 340 Jun 25 03:20 devdrwxr-xr-x.   1 root root  66 Jun 25 03:20 etcdrwxr-xr-x.   2 root root   6 Nov  3  2020 homelrwxrwxrwx.   1 root root   7 Nov  3  2020 lib -> usr/liblrwxrwxrwx.   1 root root   9 Nov  3  2020 lib64 -> usr/lib64drwx------.   2 root root   6 Dec  4  2020 lost+founddrwxr-xr-x.   2 root root   6 Nov  3  2020 mediadrwxr-xr-x.   2 root root   6 Nov  3  2020 mntdrwxr-xr-x.   2 root root   6 Nov  3  2020 optdr-xr-xr-x. 112 root root   0 Jun 25 03:20 procdr-xr-x---.   2 root root 162 Dec  4  2020 rootdrwxr-xr-x.  11 root root 163 Dec  4  2020 runlrwxrwxrwx.   1 root root   8 Nov  3  2020 sbin -> usr/sbindrwxr-xr-x.   2 root root   6 Nov  3  2020 srvdr-xr-xr-x.  13 root root   0 Jun 25 02:05 sysdrwxrwxrwt.   7 root root 145 Dec  4  2020 tmpdrwxr-xr-x.  12 root root 144 Dec  4  2020 usrdrwxr-xr-x.  20 root root 262 Dec  4  2020 var
  1. 测试ENTRYPOINT
   1. 编写 dockerfile-entrypoint-test 文件[root@bogon dockerfile]# vim dockerfile-entrypoint-testFROM centosENTRYPOINT ["ls","-a"]2. 构建镜像docker build -f dockerfile-entrypoint-test -t entrypoint-test .3. 运行之后会自动执行 ls -a 命令[root@bogon dockerfile]# docker run 94c729adceb6....dockerenvbindevetchomeliblib64lost+foundmediamntoptprocrootrunsbinsrvsystmpusrvar4. 追加运行# 实际执行的是 ls -al[root@bogon dockerfile]# docker run 94c729adceb6 -ltotal 0drwxr-xr-x.   1 root root   6 Jun 25 03:31 .drwxr-xr-x.   1 root root   6 Jun 25 03:31 ..-rwxr-xr-x.   1 root root   0 Jun 25 03:31 .dockerenvlrwxrwxrwx.   1 root root   7 Nov  3  2020 bin -> usr/bindrwxr-xr-x.   5 root root 340 Jun 25 03:31 devdrwxr-xr-x.   1 root root  66 Jun 25 03:31 etcdrwxr-xr-x.   2 root root   6 Nov  3  2020 homelrwxrwxrwx.   1 root root   7 Nov  3  2020 lib -> usr/liblrwxrwxrwx.   1 root root   9 Nov  3  2020 lib64 -> usr/lib64drwx------.   2 root root   6 Dec  4  2020 lost+founddrwxr-xr-x.   2 root root   6 Nov  3  2020 mediadrwxr-xr-x.   2 root root   6 Nov  3  2020 mntdrwxr-xr-x.   2 root root   6 Nov  3  2020 optdr-xr-xr-x. 115 root root   0 Jun 25 03:31 procdr-xr-x---.   2 root root 162 Dec  4  2020 rootdrwxr-xr-x.  11 root root 163 Dec  4  2020 runlrwxrwxrwx.   1 root root   8 Nov  3  2020 sbin -> usr/sbindrwxr-xr-x.   2 root root   6 Nov  3  2020 srvdr-xr-xr-x.  13 root root   0 Jun 25 02:05 sysdrwxrwxrwt.   7 root root 145 Dec  4  2020 tmpdrwxr-xr-x.  12 root root 144 Dec  4  2020 usrdrwxr-xr-x.  20 root root 262 Dec  4  2020 var

实战:Tomcat镜像

莫得资源,盲听

  1. 准备镜像文件,tomcat压缩包,jdk压缩包

  2. 编写DockerFile文件,官方命名DockerFile,build的时候会自动寻找这个文件,就不需要-f指定了

   FROM centosMAINTAINER ayuan<3610089198@qq.com>COPY readme.txt /usr/local/readme.txtADD jdk-8ull-linux-x64.tar.gz /usr/local                    # ADD命令,运行的时候会自动解压压缩包到指定的路径ADD apache-tomcat-9.0.22.tar.gz /usr/localRUN yum -y install vim# 配置环境变量ENV MYPATH /usr/localWORKDIR $MYPATHENV JAVA_HOME /usr/local/jdk1.8.0_11ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jarENV CATALINA_HOME /usr/local/apache-tomcat-9.0.22ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.22ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/binEXPOSE 8080CMD /usr/local/apache-tomcat-9.0.22/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.22/bin/logs/catalina.out# tail -F [文件名]:tail命令启动的时候,文件不可访问或者文件稍后变得不可访问,都始终尝试打开文件
  1. 构建镜像
   docker build -t diytomcat .  # 因为用的是官方的名字,所以可以不使用 -f [DockerFile名字] 来指定文件

运行日志截图:

  1. 启动镜像
   # 同步test信息,同步日志信息docker run -d -p 9090:8080 --name mytomcat -v /home/mytomcat/build/tomcat/test:/usr/local/apache-tomcat-9.0.22/webapps/test -v /home/kuangshen/build/tomca/tomcatlogs/:/usr/local/apache-tomcat-9.0.22/logs diytomcat
  1. 访问测试
   curl localhost:9090       # 如果可以成功访问,那么在外网也可以访问
  1. 发布项目(由于做了卷挂载,我们直接在本地编写项目就可以发布了,不必再进入容器)

    1. 进入挂载的test目录


2. 在test下创建WEB-INF目录,并在WEB-INF目录下创建web.xml文件

3. 在test下创建index.jsp文件

4. 查看日志


日志信息:

发布自己的镜像

DockerHub

  1. 地址 https://hub.docker.com/注册账号

  2. 确定账号可登录

  3. 在自己的服务器上提交自己的镜像

  1. 登录完毕后就可以提交镜像了

    这里被拒绝是因为有重复的,建议加上作者信息和版本号便于区分和维护




发布中部分日志

提交的时候也是按照层级来提交的

发布到aliyun

  1. 登录aliyun

  2. 找到容器镜像服务

  3. 创建命名空间

  4. 创建容器镜像

  5. 浏览信息

  # 公网地址:可通过这个地址来访问当前仓库


6. 发布步骤

07 Docker网络

为 容器编排 集群部署 做铺垫

理解Docker0

操作之前,将所有镜像和容器清空,单纯操作网络,方便理解

测试

# 获取当前ip地址 ip addr
# lo :本机回环地址
# enp0s3 :aliyun内网地址
# docker0 :docker生成的网卡
[root@localhost ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000link/ether 08:00:27:01:7a:d0 brd ff:ff:ff:ff:ff:ffinet 192.168.111.191/23 brd 192.168.111.255 scope global noprefixroute dynamic enp0s3valid_lft 85628sec preferred_lft 85628secinet6 fe80::846b:f00b:132c:e06d/64 scope link noprefixroute valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:88:c2:fa:a7 brd ff:ff:ff:ff:ff:ffinet 172.17.0.1/16 brd 172.17.255.255 scope global docker0valid_lft forever preferred_lft forever

三个网络

# 问题:docker是如何处理容器网络访问的?

# 容器外能否ping通容器内部?# 以tomcat为例
docker run -d -P --name tomcat01 tomcat# 查看容器的内部网络地址 ip addr ,发现容器启动的时候会得到一个 eth0@if5 的ip地址,是Docker分配的
[root@localhost ~]# docker exec -it tomcat01 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
4: eth0@if5: <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 0inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft forever# 思考:linux能不能ping通容器内部
[root@localhost ~]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.070 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.049 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.093 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.048 ms
64 bytes from 172.17.0.2: icmp_seq=5 ttl=64 time=0.081 ms
64 bytes from 172.17.0.2: icmp_seq=6 ttl=64 time=0.049 ms
64 bytes from 172.17.0.2: icmp_seq=7 ttl=64 time=0.047 ms
64 bytes from 172.17.0.2: icmp_seq=8 ttl=64 time=0.116 ms
64 bytes from 172.17.0.2: icmp_seq=9 ttl=64 time=0.053 ms
64 bytes from 172.17.0.2: icmp_seq=10 ttl=64 time=0.077 ms
64 bytes from 172.17.0.2: icmp_seq=11 ttl=64 time=0.054 ms
64 bytes from 172.17.0.2: icmp_seq=12 ttl=64 time=0.048 ms
64 bytes from 172.17.0.2: icmp_seq=13 ttl=64 time=0.071 ms
64 bytes from 172.17.0.2: icmp_seq=14 ttl=64 time=0.048 ms
64 bytes from 172.17.0.2: icmp_seq=15 ttl=64 time=0.047 ms
64 bytes from 172.17.0.2: icmp_seq=16 ttl=64 time=0.123 ms
64 bytes from 172.17.0.2: icmp_seq=17 ttl=64 time=0.047 ms
^C
--- 172.17.0.2 ping statistics ---
17 packets transmitted, 17 received, 0% packet loss, time 15999ms
rtt min/avg/max/mdev = 0.047/0.065/0.123/0.026 ms# 联系上面的容器内部查看ip的操作
# 5: vethad20ddc@if4:   和    4: eth0@if5:
[root@localhost ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000link/ether 08:00:27:01:7a:d0 brd ff:ff:ff:ff:ff:ffinet 192.168.111.191/23 brd 192.168.111.255 scope global noprefixroute dynamic enp0s3valid_lft 83012sec preferred_lft 83012secinet6 fe80::846b:f00b:132c:e06d/64 scope link noprefixroute valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:88:c2:fa:a7 brd ff:ff:ff:ff:ff:ffinet 172.17.0.1/16 brd 172.17.255.255 scope global docker0valid_lft forever preferred_lft foreverinet6 fe80::42:88ff:fec2:faa7/64 scope link valid_lft forever preferred_lft forever
5: vethad20ddc@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default link/ether 22:66:b7:47:47:45 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet6 fe80::2066:b7ff:fe47:4745/64 scope link valid_lft forever preferred_lft forever

  1. 我们每启动一个docker容器,docker就会给docker容器分配一个ip,只要安装了docker,就会有一个网卡docker0桥接模式,使用的技术是evth-pair技术

    再次测试ip addr


  1. 再启动一个tomcat02
   docker run -d -P --name tomcat02 tomcat# 查看容器内ip情况[root@localhost ~]# docker exec -it cefb489bcb51 ip addr1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft forever# 查看linux ip情况[root@localhost ~]# ip addr1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000link/ether 08:00:27:01:7a:d0 brd ff:ff:ff:ff:ff:ffinet 192.168.111.191/23 brd 192.168.111.255 scope global noprefixroute dynamic enp0s3valid_lft 84897sec preferred_lft 84897secinet6 fe80::846b:f00b:132c:e06d/64 scope link noprefixroute valid_lft forever preferred_lft forever3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:d4:f1:fe:cf brd ff:ff:ff:ff:ff:ffinet 172.17.0.1/16 brd 172.17.255.255 scope global docker0valid_lft forever preferred_lft foreverinet6 fe80::42:d4ff:fef1:fecf/64 scope link valid_lft forever preferred_lft forever5: veth1beee03@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default link/ether 6e:56:36:f2:64:6a brd ff:ff:ff:ff:ff:ff link-netnsid 0inet6 fe80::6c56:36ff:fef2:646a/64 scope link valid_lft forever preferred_lft forever7: vethc94a5e8@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default link/ether 2a:cd:89:5a:e0:9e brd ff:ff:ff:ff:ff:ff link-netnsid 1inet6 fe80::28cd:89ff:fe5a:e09e/64 scope link valid_lft forever preferred_lft forever

可以看出来多了一组6 7 ,每启动一个容器,docker分配的ip都是成对出现的(会多一对网卡)

  1. 通过测试结果,我们发现这个容器带来的网卡,都是一对对的
  2. veth-pair(Virtual Ethernet - VETH) 是一对的虚拟设备接口,他们都是成对出现的,一段连着协议栈,一段彼此相连,数据从一端出,从另一端进。
  3. 正因为有这个特性,veth-pair充当一个桥梁,连接各种虚拟网络设备
  4. openStac,Docker容器之间的连接,OVS的连接,都是使用veth-pair 技术
  1. 下面来测试tomcat01和tomcat02是否能ping通
   # 查看tomcat01的ip[root@localhost ~]# docker exec -it tomcat01 ip addr1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever4: eth0@if5: <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 0inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft forever# 查看tomcat02的ip[root@localhost ~]# docker exec -it tomcat02 ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft forever# tomcat01 ping tomcat02   可以ping通root@72c65e1c7c34:/usr/local/tomcat# ping 172.17.0.3PING 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.175 ms64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.073 ms64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.076 ms64 bytes from 172.17.0.3: icmp_seq=4 ttl=64 time=0.063 ms64 bytes from 172.17.0.3: icmp_seq=5 ttl=64 time=0.064 ms64 bytes from 172.17.0.3: icmp_seq=6 ttl=64 time=0.149 ms64 bytes from 172.17.0.3: icmp_seq=7 ttl=64 time=0.073 ms^C--- 172.17.0.3 ping statistics ---7 packets transmitted, 7 received, 0% packet loss, time 7msrtt min/avg/max/mdev = 0.063/0.096/0.175/0.042 ms




结论:tomcat01和tomcat02是共用的一个路由器:docker0

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

Docker使用的是Linux的桥接

Docker中所有的网络接口都是虚拟的,因为虚拟的转发效率高, 如内网传递文件的时候速度会很快

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

–link

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

[root@localhost ~]# docker ps
CONTAINER ID   IMAGE     COMMAND             CREATED       STATUS       PORTS                                         NAMES
cefb489bcb51   tomcat    "catalina.sh run"   2 hours ago   Up 2 hours   0.0.0.0:49154->8080/tcp, :::49154->8080/tcp   tomcat02
72c65e1c7c34   tomcat    "catalina.sh run"   2 hours ago   Up 2 hours   0.0.0.0:49153->8080/tcp, :::49153->8080/tcp   tomcat01# 使用容器名称是否可以ping通?
[root@localhost ~]# docker exec -it tomcat01 ping tomcat02
ping: tomcat02: Name or service not known# 需要借助--link 解决网络联通问题
[root@localhost ~]# docker run -d -P --name tomcat03 --link tomcat02 tomcat
2d2101d11ea9783e09816922a36af7587ed0df996dc72ebb47f8c3d6007ac36c
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE     COMMAND             CREATED              STATUS              PORTS                                         NAMES
2d2101d11ea9   tomcat    "catalina.sh run"   About a minute ago   Up About a minute   0.0.0.0:49155->8080/tcp, :::49155->8080/tcp   tomcat03
cefb489bcb51   tomcat    "catalina.sh run"   2 hours ago          Up 2 hours          0.0.0.0:49154->8080/tcp, :::49154->8080/tcp   tomcat02
72c65e1c7c34   tomcat    "catalina.sh run"   2 hours ago          Up 2 hours          0.0.0.0:49153->8080/tcp, :::49153->8080/tcp   tomcat01# 能否反向ping通
[root@localhost ~]# 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.098 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.064 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=3 ttl=64 time=0.067 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=4 ttl=64 time=0.064 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=5 ttl=64 time=0.064 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=6 ttl=64 time=0.108 ms
^C
--- tomcat02 ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 5ms
rtt min/avg/max/mdev = 0.064/0.077/0.108/0.020 ms
[root@localhost ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known

# 查看网络信息
[root@localhost ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
674a0a5fd456   bridge    bridge    local        # 本地
ffae12332cc3   host      host      local
9ea8d2221bad   none      null      local# 查看网卡信息
[root@localhost ~]# docker inspect 674a0a5fd456
[{"Name": "bridge","Id": "674a0a5fd45657796a4653c19ec56e63fd4db39d38d1393549e2a2a365e8e37d","Created": "2021-06-28T10:34:19.66050121+08:00","Scope": "local","Driver": "bridge","EnableIPv6": false,"IPAM": {"Driver": "default","Options": null,"Config": [{"Subnet": "172.17.0.0/16","Gateway": "172.17.0.1"         # 默认网关,即docker0}]},"Internal": false,"Attachable": false,"Ingress": false,"ConfigFrom": {"Network": ""},"ConfigOnly": false,"Containers": {"6dc2e56fd0fac553beeeb9f0bbbf0a8be2a384fbdd7650d3c1958a490eb9d642": {"Name": "tomcat03","EndpointID": "dd12f53b7dbdc1b9c9179f602cb4724cb0f4f99ca4d3a2011563c5558378ee4e","MacAddress": "02:42:ac:11:00:04","IPv4Address": "172.17.0.4/16","IPv6Address": ""},"9a0634536a9c32292d31ba4a06c710ab69800dc36eeebc157f7703b44b80b9a7": {"Name": "tomcat01","EndpointID": "a1d11eb40afe5b77c6956c72f0ca1d2adeec808c4ae7f51dd67fd8c74541dc9d","MacAddress": "02:42:ac:11:00:02","IPv4Address": "172.17.0.2/16","IPv6Address": ""},"b57bca4a2492424eb6829f7e6403fa146be806ef7d1ed629694b8f58b28bfd18": {"Name": "tomcat02","EndpointID": "aa63c7783d04a04bb8716b34fa9778cfadd030d8dbf7e2c85ffff4201560440e","MacAddress": "02:42:ac:11:00:03","IPv4Address": "172.17.0.3/16","IPv6Address": ""}},"Options": {"com.docker.network.bridge.default_bridge": "true","com.docker.network.bridge.enable_icc": "true","com.docker.network.bridge.enable_ip_masquerade": "true","com.docker.network.bridge.host_binding_ipv4": "0.0.0.0","com.docker.network.bridge.name": "docker0","com.docker.network.driver.mtu": "1500"},"Labels": {}}
]


探究 inspect

tomcat01 02 03

查看tomcat03的详细信息

原理探究

# 查看tomcat03的hosts信息
[root@localhost ~]# 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 b57bca4a2492       # 所以tomcat03可以ping通tomcat02
172.17.0.4      6dc2e56fd0fa                # tomcat03自身# 再来查看下tomcat02
[root@localhost ~]# docker exec -it tomcat02 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      b57bca4a2492                # 只有tomcat02自身# 若要使tomcat02 ping通tomcat03,需要重启tomcat02加配置

本质探究:–link 就是我们在hosts配置中增加了一个172.17.0.3 的 tomcat02 b57bca4a2492

目前不建议使用–link,比起docker0,建议使用自定义网络.

docker0缺点:不支持容器名连接访问

自定义网络

查看所有的docker网络[root@localhost ~]# docker network lsNETWORK ID     NAME      DRIVER    SCOPE674a0a5fd456   bridge    bridge    localffae12332cc3   host      host      local9ea8d2221bad   none      null      local

网络模式

bridge:桥接模式. 在 docker上搭桥 (默认,自己创建的时候也使用这个模式)

none:不配置网络(一般不使用)

host:和宿主机共享网络

container:容器网络联通(用的少,局限很大)

测试

# 我们直接启动的命令 --net bridge,而这个就是我们的docker0
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat01 --net bridge tomcat# docker0特点:1. 默认   2. 域名不能访问   3. --link可以打通连接# 我们可以自定义一个网络
[root@localhost ~]# docker network create --helpUsage:  docker network create [OPTIONS] NETWORKCreate a networkOptions:--attachable           Enable manual container attachment--aux-address map      Auxiliary IPv4 or IPv6 addresses used by Network driver (default map[])--config-from string   The network from which to copy the configuration--config-only          Create a configuration only network-d, --driver string        Driver to manage the Network (default "bridge")--gateway strings      IPv4 or IPv6 Gateway for the master subnet--ingress              Create swarm routing-mesh network--internal             Restrict external access to the network--ip-range strings     Allocate container ip from a sub-range--ipam-driver string   IP Address Management Driver (default "default")--ipam-opt map         Set IPAM driver specific options (default map[])--ipv6                 Enable IPv6 networking--label list           Set metadata on a network-o, --opt map              Set driver specific options (default map[])--scope string         Control the network's scope--subnet strings       Subnet in CIDR format that represents a network segment# --driver bridge          规定网络模式 默认是网桥
# --subnet 192.168.0.0/16  规定子网 192.168.0.0/16  192.168.0.2 ~ 192.168.255.255
# --gateway 192.168.0.1    规定网关名[root@localhost ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
d642a24a250ddef9662f7091362596c6ea76d809f0e1b1d8418a5747dce2d921# 列出所有网络
[root@localhost ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
674a0a5fd456   bridge    bridge    local
ffae12332cc3   host      host      local
d642a24a250d   mynet     bridge    local
9ea8d2221bad   none      null      local# 查看指定网络详细信息
[root@localhost ~]# docker inspect d642a24a250d
[{"Name": "mynet","Id": "d642a24a250ddef9662f7091362596c6ea76d809f0e1b1d8418a5747dce2d921","Created": "2021-06-28T14:27:24.063041512+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": {},"Options": {},"Labels": {}}
]
# 在自己的网络启动
[root@localhost ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat
[root@localhost ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat # 查看ip
[root@localhost ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000link/ether 08:00:27:01:7a:d0 brd ff:ff:ff:ff:ff:ffinet 192.168.111.191/23 brd 192.168.111.255 scope global noprefixroute dynamic enp0s3valid_lft 70380sec preferred_lft 70380secinet6 fe80::846b:f00b:132c:e06d/64 scope link noprefixroute valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:44:50:c8:c1 brd ff:ff:ff:ff:ff:ffinet 172.17.0.1/16 brd 172.17.255.255 scope global docker0valid_lft forever preferred_lft foreverinet6 fe80::42:44ff:fe50:c8c1/64 scope link valid_lft forever preferred_lft forever
10: br-d642a24a250d: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:86:d2:82:2f brd ff:ff:ff:ff:ff:ffinet 192.168.0.1/16 brd 192.168.255.255 scope global br-d642a24a250dvalid_lft forever preferred_lft foreverinet6 fe80::42:86ff:fed2:822f/64 scope link valid_lft forever preferred_lft forever
12: veth5d49e7b@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-d642a24a250d state UP group default link/ether 12:25:f6:b1:16:8d brd ff:ff:ff:ff:ff:ff link-netnsid 0inet6 fe80::1025:f6ff:feb1:168d/64 scope link valid_lft forever preferred_lft forever
14: veth380147e@if13: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-d642a24a250d state UP group default link/ether a6:50:b2:1b:01:73 brd ff:ff:ff:ff:ff:ff link-netnsid 1inet6 fe80::a450:b2ff:fe1b:173/64 scope link valid_lft forever preferred_lft forever

再次测试是否可以ping

# 查看ip# 查出的ip是 192.168.0.2
[root@localhost ~]# docker inspect tomcat-net-01# 查出的ip是 192.168.0.3
[root@localhost ~]# docker inspect tomcat-net-02# 测试是否能ping通
# ping ip
[root@localhost ~]# docker exec -it tomcat-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.111 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.062 ms
64 bytes from 192.168.0.3: icmp_seq=3 ttl=64 time=0.070 ms
64 bytes from 192.168.0.3: icmp_seq=4 ttl=64 time=0.081 ms
64 bytes from 192.168.0.3: icmp_seq=5 ttl=64 time=0.070 ms
64 bytes from 192.168.0.3: icmp_seq=6 ttl=64 time=0.068 ms
64 bytes from 192.168.0.3: icmp_seq=7 ttl=64 time=0.070 ms
^C
--- 192.168.0.3 ping statistics ---
7 packets transmitted, 7 received, 0% packet loss, time 1005ms
rtt min/avg/max/mdev = 0.062/0.076/0.111/0.015 ms# ping [名字]
[root@localhost ~]# docker exec -it tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.068 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.065 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.060 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=4 ttl=64 time=0.065 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=5 ttl=64 time=0.063 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=6 ttl=64 time=0.066 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=7 ttl=64 time=0.074 ms
^C
--- tomcat-net-02 ping statistics ---
7 packets transmitted, 7 received, 0% packet loss, time 7ms
rtt min/avg/max/mdev = 0.060/0.065/0.074/0.011 ms

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

自定义网络好处

  1. redis:不同的集群使用不同的网络,保证集群是安全和健康的
  2. mysql:不同的集群使用不同的网络,保证集群是安全和健康的

网络连通

# 现在再启动两个tomcat
[root@localhost ~]# docker run -d -P --name tomcat01 tomcat
bb981cf01e5ac7a5aca1657ecbc030fa7c0fea8f86af1f20242d8198ed84dac9
[root@localhost ~]# docker run -d -P --name tomcat02 tomcat
f162c6c2bc87cc8955652f6d7dae20623a3f9bc357462bd068e83ca840d9a224

处于不同网段是无法ping通的,需要将这两个网络打通,这里的打通不是网卡的打通,因为网卡打通网络就变了

实际上的打通: 容器可以与mynet连接

打通

[root@localhost ~]# docker network --helpUsage:  docker network COMMANDManage networksCommands:connect     Connect a container to a network    # 使用这个命令打通create      Create a networkdisconnect  Disconnect a container from a networkinspect     Display detailed information on one or more networksls          List networksprune       Remove all unused networksrm          Remove one or more networksRun 'docker network COMMAND --help' for more information on a command.# 打通命令
[root@localhost ~]# docker network connect --helpUsage:  docker network connect [OPTIONS] NETWORK CONTAINERConnect a container to a networkOptions:--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

测试打通tomcat01 - mynet

# 打通 tomcat01 和 mynet
[root@localhost ~]# docker network connect mynet tomcat01# 查看网络信息
# 连通之后将tomcat01加到了mynet网段中
[root@localhost ~]# docker network inspect mynet
[{"Name": "mynet","Id": "d642a24a250ddef9662f7091362596c6ea76d809f0e1b1d8418a5747dce2d921","Created": "2021-06-28T14:27:24.063041512+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": {"0d201a7005a2f1ec91e8c84f198bfd0b191efd7fc558e8d47e2f37e8a409217f": {"Name": "tomcat-net-02","EndpointID": "965a834538bb56dc68e07af40e947a8a0e2ad4710131b87b2c8672a4060db588","MacAddress": "02:42:c0:a8:00:03","IPv4Address": "192.168.0.3/16","IPv6Address": ""},"bb981cf01e5ac7a5aca1657ecbc030fa7c0fea8f86af1f20242d8198ed84dac9": {"Name": "tomcat01",              # 连通之后将tomcat01加到了mynet网段中"EndpointID": "1a9a877b9bf5165890bbb6c03e6ab727f205ef1ad10b8c9c9ac0d4615492dbd0","MacAddress": "02:42:c0:a8:00:04","IPv4Address": "192.168.0.4/16","IPv6Address": ""},"ca3ca4b2ca9bf2df3fcebea7b97e3ce4d103ff4db90ce9340efc1a293cd8859a": {"Name": "tomcat-net-01","EndpointID": "1418d84aa7a7729e174b0de7d16624aaf37eb99b840a3a3889db3dd88bc0e4e4","MacAddress": "02:42:c0:a8:00:02","IPv4Address": "192.168.0.2/16","IPv6Address": ""}},"Options": {},"Labels": {}}
]
# 连通之后将tomcat01加到了mynet网段中
# 之后 tomcat-net-01 tomcat-net-02 tomcat01 可两两互通,但是tomcat02是不通的

打通原理:一个容器两个ip:公网ip 和 私网ip

结论:假设要跨网络操作别人的网段,就需要使用 docker connect 进行连通

实战:部署redis集群 有问题 暂鸽

分片 + 高可用 + 负载均衡

  1. 创建一个网段
   docker network create redis --subnet 172.38.0.0/16# 查看信息[root@localhost ~]# docker network inspect redis[{"Name": "redis","Id": "99fe646b16089b694bda63f4a40de2e2e5d627499e3baed9fb3ecc90a4565f99","Created": "2021-06-28T16:12:28.921356782+08:00","Scope": "local","Driver": "bridge","EnableIPv6": false,"IPAM": {"Driver": "default","Options": {},"Config": [{"Subnet": "172.38.0.0/16"}]},"Internal": false,"Attachable": false,"Ingress": false,"ConfigFrom": {"Network": ""},"ConfigOnly": false,"Containers": {},"Options": {},"Labels": {}}]
  1. 通过脚本创建6个redis服务
   for port in $(seq 1 6);domkdir -p /mydata/redis/node-${port}/conftouch /mydata/redis/node-${port}/conf/redis.confcat << EOF >/mydata/redis/node-${port}/conf/redis.confport 6379bind 0.0.0.0cluster-enabled yescluster-config-file nodes.confcluster-node-timeout 5000cluster-announce-ip 172.38.0.1${port}cluster-announce-port 6379cluster-announce-bus-port 16379appendonly yesEOFdone
  1. 查看下信息
   [root@localhost ~]# cd /mydata/[root@localhost mydata]# cd redis[root@localhost redis]# lsnode-1  node-2  node-3  node-4  node-5  node-6[root@localhost redis]# cd node-1[root@localhost node-1]# lsconf[root@localhost node-1]# cd conf[root@localhost conf]# lsredis.conf# 查看写入的配置信息[root@localhost conf]# cat redis.conf port 6379bind ...cluster-enabled yescluster-config-file nodes.confcluster-node-timeout 5cluster-announce-ip 172.38..11cluster-announce-port 6379cluster-announce-bus-port 16379appendonly yes
  1. 启动命令 脚本有问题
 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# 运行日志[root@localhost ~]# 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.confUnable to find image 'redis:5.0.9-alpine3.11' locally5.0.9-alpine3.11: Pulling from library/rediscbdbe7a5bc2a: Pull complete dc0373118a0d: Pull complete cfd369fe6256: Pull complete 3e45770272d9: Pull complete 558de8ea3153: Pull complete a2c652551612: Pull complete Digest: sha256:83a3af36d5e57f2901b4783c313720e5fa3ecf0424ba86ad9775e06a9a5e35d0Status: Downloaded newer image for redis:5.0.9-alpine3.1195f3bf4958e0b392c5628d91d8cd096cf93ca547c0c26fed7530ae1b3722f434# 依次启动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

SpringBoot微服务打包Docker镜像


本地测试没问题后,点击clean 再package打包

打包结果:

之后创建DockerFile文件,

发布的时候发布的是打包好的jar包,和DockerFile文件

步骤:

  1. 构架SpringBoot项目
  2. 打包应用(xxx.jar)
  3. 编写DockerFile(为了将xxx.jar拷贝到容器内部)
  4. 构建镜像(拷贝jar包作为镜像)
  5. 发布运行

Docker进阶

  1. Docker Compose
  2. Docker Swarm
  3. CI/CD 之 Jenkins

done.

【Docker】总集篇相关推荐

  1. python docker自动化_「docker实战篇」python的docker爬虫技术-移动自动化控制工具appium工具(17)...

    原创文章,欢迎转载.转载请注明:转载自 IT人故事会,谢谢! 原文链接地址: 「docker实战篇」python的docker爬虫技术-移动自动化控制工具appium工具(17) Appium是一个开 ...

  2. python docker自动化_「docker实战篇」python的docker爬虫技术-移动自动化控制工具安卓ADB的使用(15)...

    原创文章,欢迎转载.转载请注明:转载自 IT人故事会,谢谢! 原文链接地址: 「docker实战篇」python的docker爬虫技术-移动自动化控制工具安卓ADB的使用(15) adb(Androi ...

  3. 「docker实战篇」python的docker爬虫技术-在linux下mitmproxy介绍和安装(四)

    原创文章,欢迎转载.转载请注明:转载自IT人故事会,谢谢! 原文链接地址:「docker实战篇」python的docker爬虫技术-在linux下mitmproxy介绍和安装(四) 上次说了fiddl ...

  4. 尚硅谷docker基础篇 2018版

    typora-root-url: ./image Docker基础篇之快速上手 第一章 Docker简介 是什么? 问题:为什么会有 docker 的出现 一款产品从开发到上线,从操作系统,到运行环境 ...

  5. 「docker实战篇」python的docker爬虫技术-安卓模拟器(二)

    原创文章,欢迎转载.转载请注明:转载自IT人故事会,谢谢! 原文链接地址:「docker实战篇」python的docker爬虫技术-安卓模拟器(二) 为什么要手机模拟器,如果有条件正好有不使用的安卓手 ...

  6. Docker基础篇之快速上手

    下载md查看 链接:https://pan.baidu.com/s/1ocFFFlOvGZdXBDgJovZ8tA 提取码:atm3 Docker基础篇之快速上手 第一章 Docker简介 是什么? ...

  7. Docker整理篇(docker-compose与私服搭建)

    Docker整理篇(docker-compose) 安装与常用命令操作 Docker网络与数据卷 docker-compose与私服搭建 基本介绍 官网地址 https://docs.docker.c ...

  8. 《docker基础篇:8.Docker常规安装简介》包括:docker常规安装总体步骤、安装tomcat、安装mysql、安装redis

    文章目录 8.Docker常规安装简介 8.1 docker常规安装总体步骤 8.2安装tomcat 8.3 安装mysql 8.3.1 docker hub上面查找mysql镜像 8.3.2 从do ...

  9. 「docker实战篇」python的docker-打造多任务端app应用数据抓取系统(下)(35)

    上次已经把python文件挂载到虚拟机上了,这次主要设置下虚拟机通过docker容器的方式. 运行 python 代码运行 >启动一个crt的会话 docker run -it -v /root ...

  10. Docker筑基篇-上

    Docker筑基篇 1.Docker安装心酸历程 1.1.卸载旧的版本 1.2.安装一些docker需要的安装包 1.3.设置镜像仓库 1.4.安装docker引擎 1.5.启动docker 1.6. ...

最新文章

  1. git 版本控制系统初学
  2. [递归]递归问题解题思路
  3. STM32-----找个搬砖的搬数据
  4. oracle19c 安装权限_redhat7.6Linux安装Oracle19C完整版教程
  5. 10.卷1(套接字联网API)---SCTP 客户/服务器程序例子
  6. 七代处理器装win7_七代cpu为什么不支持win7?
  7. 【随文杂想】超长图PS 切片为打印机 A4纸大小打印
  8. GroovyHelp
  9. 高可用pxc+rocketmq+es+redis+minio+keepalive+haproxy 实操
  10. html无法访问页面,为什么网页无法访问?
  11. php mysql 白屏_PHP出现空白页面与无法载入mysql
  12. PPT中要实现图片或图形的任意拖拽
  13. AMBA总线---APB总线协议
  14. MySQL密码忘记了如何操作
  15. stm32c8t6+dht11+MQ系列环境检测模块+oled显示屏(基于物联网的家庭环境检测系统设计)
  16. apache更改网站目录
  17. php 表情 代码_PHP 大量QQ表情代码替换
  18. 利用计算机实现音乐节拍的实时自动跟踪,音乐节拍实时跟踪系统的研究及应用...
  19. TDOA算法综述(An overview of TDOA algorithm)--(1)
  20. SystemUI常见问题修改方法

热门文章

  1. 富国银行眼下乱成一团糟:数据中心被烟雾笼罩,银行网站和应用软件宕机
  2. 推荐:年度巨献:《Ubuntu桌面生存指南》(作者:ghosert)
  3. 2020阿里云线上峰会预告 | 凌云时刻
  4. 阿里张勇《人民日报》刊发署名文章:抓住数字新基建的机遇
  5. 智汇华云 | 异步?NO! 同步?NO! 华云数据新专利解决云平台容灾难题
  6. 【优化求解】基于matlab模拟退火算法求解函数极值问题【含Matlab源码 1203期】
  7. kali linux 桌面消失_Kali安装好后,需要修改的一些常用配置
  8. 游戏世界观构建_我们如何构建技术落后的世界
  9. wp-autoblog_AutoBlog简介
  10. 标准化画图【cmap】【imshow】【EllipseSkyRegion】【contour】【set_ticklabels】【coords】【colorbar】