这是我学习Docker容器技术的全部过程,所有的案例全部实现,尽管学习过程中遇到很多困难和问题,但是我从未放弃,经过努力逐一解决,颇有收获。以下的学习过程主要是在CentOS7系统环境,有部分在Win10和Mac系统操作。

Docker 学习

  • Docker 概述

  • Docker 安装

  • Docker 命令

    ​ 。镜像命令

    ​ 。容器命令

    ​ 。操作命令

    ​ 。…

  • Docker 镜像

  • 容器数据卷

  • Dockerfile

  • Docker网络原理

  • IDEA 整合Docker


Docker概述


Docker 为什么出现?


一款产品:开发–上线 两套环境, 应用环境, 应用配置!开发–运维 问题:我在我电脑可以运行!版本更新,导致服务不可用,对运维考验很大。环境配置是十分麻烦,每一个机器都要部署环境(集群Redis, ES,Hadoop…)费时费力
发布一个项目(jar包+(Redis MySQL jdk ES),项目能不能带上环境。安装打包之前在服务器配置一个应用环境Redis MySQL jdk ES Hadoop,配置超麻烦, 不能跨平台,Windows 发布到Linux。现在开发包部署上线,一套流程做完。java – jar(环境)-- 打包项目带上没环境(镜像)-- (Docker仓库:商店 – 下载我们发布的镜像 – 直接运行即可。Docker给以上的问题,提供了解决方案。

img

Docker的思想来自于集装箱

JRE – 多个应用(端口冲突)-- 原来都是交叉的

隔离:Docker核心思想,打包装箱,每个箱子是互相隔离的。

Docker通过隔离机制,可以将服务器利用到极致


Docker的历史


2010年,几个搞IT的年轻人,在美国成立一家公司dotCloud,做一些pass的云计算服务,LXC有关的容器技术

他们将自己的技术(容器化技术)命名Docker

开源:

开发源代码

2013年,Docker开源(开放源代码)

2014年4月9日,Docker1.0发布,容器技术出现之前,都是虚拟机技术。

虚拟机:在windows中安装一个VMware,通过这个软件我们可以虚拟出一台或者多台电脑,耗资源。

虚拟机也是虚拟化技术,Docker容器技术,也是一种虚拟化技术。

vm:linux centos原生镜像(一个电脑)隔离,需要开启多个虚拟机
docker:隔离,镜像(最核心的环境)

Docker基于Go语言开发,开源项目!

官网:https://www.docker.com/

文档地址:https://docs.docker.com/ Docker的文档是超级详细的

仓库地址:https://hub.docker.com/ git push pull

Docker 能干什么?

虚拟机技术缺点:

1、资源占用十分多

2、冗余步骤多

3、启动很慢

容器化技术:

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

比较Docker和虚拟机技术的不同

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

DevOps(开发、运维)

应用更快速的交付和部署

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

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

更便捷的升级和扩容

使用Docker以后,我们部署应用就像搭积木一样

项目打包为一个镜像,扩展服务器A 服务器B

更简单的系统运维

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

更高效的计算资源利用:

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


Docker安装


Docker的基本组成

点击查看源网页

镜像(image):

​ docker镜像好比是一个模板,可以通过这个模板来创建容器服务,tomcat镜像===>run==>tomcat01容器(提供服务器)

​ 通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中)

容器(container):

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

​ 启动,停止,删除,基本命令

​ 目前就可以把这个容器理解为就是一个简易的Linux系统

仓库(repository):

​ 仓库就是存放镜像的地方

​ 仓库分为公有仓库和私有仓库

​ Docker Hub(默认是国外的)

​ 阿里云…都有容器服务


安装Docker

环境准备

​ 1、需要linux基础知识

​ 2、CentOS7

​ 3、我们使用Xshell连接远程服务器进行操作

环境查看

# 系统内核是3.10以上
[root@localhost ~]# uname -r
3.10.0-1160.42.2.el7.x86_64
# 系统版本
[root@localhost ~]# cat /etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"

安装

帮助文档:

# 1.卸载旧版
$sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
                  
# 2.需要的安装包
$sudo yum install -y yum-utils
# 3.设置镜像的仓库
$sudo yum-config-manager \
    --add-repo \
https://download.docker.com/linux/centos/docker-ce.repo  # 默认是国外的镜像地址
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo  # 推荐使用国内的阿里云镜像地址
# 4.更新软件包索引
$sudo yum makecache fast  
# 5.安装docker, docker-ce  社区版   docker-ee 企业版
$sudo yum install docker-ce docker-ce-cli containerd.io    # 官方推荐使用社区版


# 可以列出和分类docker版本
$ yum list docker-ce --showduplicates | sort -r

# 安装指定版本的docker
$sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io

# 6. 启动docker
$sudo systemctl start docker
# 7. 判断启动成功
# docker version
[root@localhost ~]# docker version
Client: Docker Engine - Community
 Version:           20.10.8
 API version:       1.41
 Go version:        go1.16.6
 Git commit:        3967b7d
 Built:             Fri Jul 30 19:55:49 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.8
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.6
  Git commit:       75249d8
  Built:            Fri Jul 30 19:54:13 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.4.9
  GitCommit:        e25210fe30a0a703442421b0f60afac609f950a3
 runc:
  Version:          1.0.1
  GitCommit:        v1.0.1-0-g4144b63
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
  
  # 8.hello-word
$sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:2498fce14358aa50ead0cc6c19990fc6ff866ce72aeb5546e1d59caac3d0d60f
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/
 
 # 9.查看一下下载的这个hello-world镜像 
[root@localhost ~]# docker images
REPOSITORY      TAG       IMAGE ID       CREATED        SIZE
mysql           5.7       c20987f18b13   2 weeks ago    448MB
ubuntu          latest    ba6acccedd29   2 months ago   72.8MB
hello-world     latest    feb5d9fea6a5   3 months ago   13.3kB
mariadb         latest    6b01262bc780   4 months ago   409MB
vulhub/discuz   x3.4      5a979b3474c5   4 years ago    441MB

了解:卸载docker

 # 1.卸载依赖
 $sudo yum remove docker-ce docker-ce-cli containerd.io
 # 2.删除资源
 $sudo rm -rf /var/lib/docker     # dockers的默认工作路径
 $sudo rm -rf /var/lib/containerd

阿里云镜像加速


1、登录阿里云找到容器服务

2、找到镜像加速的地址

3、配置使用

$sudo mkdir -p /etc/docker

$sudo tee /etc/docker/daemon.json <<-'EOF'
{
	"registry-mirrors":["https://bruce_liu1973@163.com.mirror.aliyuncs.com"]
}
EOF
$sudo systemctl daemon-reload
$sudo systemctl restart docker

回顾HelloWorld流程

1、开始---->docker在本机寻找镜像---->判断是否存在 ---->存在启动本机镜像

2、开始---->docker在本机寻找镜像---->判断是否存在 ---->不存在---->去docker hub下载----->找到下载到本地---->启动


底层原理

Docker是怎么工作的?

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

Docker的常用命令

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

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

镜像命令


1、docker images 查看所有本地的主机上的镜像
# Windows系统环境
C:\cmder
λ docker images
REPOSITORY                  TAG                                                     IMAGE ID       CREATED         SIZE
docker/getting-started      latest                                                  26d80cd96d69   4 weeks ago     28.5MB
docker/desktop-kubernetes   kubernetes-v1.22.4-cni-v0.8.5-critools-v1.17.0-debian   493a106d3678   6 weeks ago     294MB
scrapinghub/splash          latest                                                  9364575df985   16 months ago   1.89GB
# 解释
REPOSITORY    镜像的仓库源
TAG 		 镜像的标签
IMAGE ID	 镜像的id
CREATED		 镜像的创建时间
SIZE		 镜像的大小

# 可选项
                                                                           
Options:                                                                   
  -a, --all             Show all images (default hides intermediate images)   # 列出所有镜像                           -q, --quiet           Only show image IDs                                   # 只显示ID
  
  

2、docker search搜索镜像

官网地址:https://hub.docker.com/

# Windows系统环境
docker search mysql
C:\cmder
λ docker search mysql
NAME                              DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql                             MySQL is a widely used, open-source relation…   11909     [OK]
mariadb                           MariaDB Server is a high performing open sou…   4556      [OK]
mysql/mysql-server                Optimized MySQL Server Docker images. Create…   894                  [OK]

# 可选项
docker search --help
Options:
  -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
#通过收藏来过滤
--filter=STARS=3000  # 搜索出来的镜像就是STARS超过3000的

C:\cmder
λ docker search mysql --filter=STARS=4000
NAME      DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql     MySQL is a widely used, open-source relation…   11909     [OK]
mariadb   MariaDB Server is a high performing open sou…   4556      [OK]

docker pull 下载镜像

# Windows系统环境
C:\cmder
λ docker pull --help

Usage:  docker pull [OPTIONS] NAME[:TAG|@DIGEST]

Pull an image or a repository from a registry

Options:
  -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
  # 下载镜像
C:\cmder                                                                              
λ docker pull mysql                                                                   
Using default tag: latest              #如果不写tag,默认就是latest                                                     
latest: Pulling from library/mysql                                                    
72a69066d2fe: Pull complete      	   # 分层下载,docker images的核心,联合文件系统
93619dbc5b36: Pull complete                                                           
99da31dd6142: Pull complete                                                           
626033c43d70: Pull complete                                                           
37d5d7efb64e: Pull complete                                                           
ac563158d721: Pull complete                                                           
d2ba16033dad: Pull complete                                                           
688ba7d5c01a: Pull complete                                                           
00e060b6d11d: Pull complete                                                           
1c04857f594f: Pull complete                                                           
4d7cfa90e6ea: Pull complete                                                           
e0431212d27d: Pull complete                                                           
Digest: sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709       # 签名
Status: Downloaded newer image for mysql:latest                                       
docker.io/library/mysql:latest													# 真实地址   

# 等价命令
docker pull mysql
docker pull docker.io/library/mysql:latest

# 下载镜像 指定版本
docker pull mysql:5.7 

C:\cmder                                                                        
λ docker pull mysql:5.7                                                         
5.7: Pulling from library/mysql                                                 
72a69066d2fe: Already exists                                                    
93619dbc5b36: Already exists                                                    
99da31dd6142: Already exists                                                    
626033c43d70: Already exists                                                    
37d5d7efb64e: Already exists                                                    
ac563158d721: Already exists                                                    
d2ba16033dad: Already exists                                                    
0ceb82207cd7: Pull complete                                                     
37f2405cae96: Pull complete                                                     
e2482e017e53: Pull complete                                                     
70deed891d42: Pull complete                                                     
Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94 
Status: Downloaded newer image for mysql:5.7                                    
docker.io/library/mysql:5.7                                                     
# 查看所有的镜像

docker 删除镜像

docker rmi -f c20987f18b13   # image id  删除指定的镜像
docker rmi -f 容器id 容器id 容器id 容器id  #删除多个容器
docker rmi -f $(docker images -aq)  #删除所有的镜像   -aq是所有的镜像 $()传参

容器命令

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

docker run --help  #docker run启动
新建容器并启动
docker run[可选参数] image
# 参数说明
--name="Name"  容器名字 tomcat 01 tomcat02 用来区分容器
-d 			  后台方式运行
-it            使用交互方式运行, 进入容器查看内容
-P 			  指定容器的端口 -p 8080:8080
	-p ip:主机端口:容器端口
	-P 主机端口:容器端口(常用)
	-P 容器端口
-p			  随机指定端口
# 测试
docker run -it centos /bin/bash

# 从容器退回主机
exit


列出所有运行的容器
docker ps 
docker ps -a   #列出当前正在运行的容器+历史运行过的容器
docker ps -n=?  # 显示最近创建的容器
docker ps -n=1
docker ps -q     #只显示容器的编号
docker ps -aq    # 显示所有容器的编号
退出容器
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 镜像名
docker run -d 镜像名
# 问题docker ps 发现centos 停止了
# 常见的坑:docker 容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止
# nginx, 容器启动后,发现自己没有提供服务,就会立刻停止,就没有程序了。
查看日志
docker logs
docker logs --help    # 选项
docker logs -f -t --tail 容器id    # 容器,没有日志
# 自己编写shell脚本
"while true;do echo bruce_liu;sleep 1;done"
docker run -d centos -c  /bin/sh "while true;do echo bruce_liu;sleep 1;done" 
# 显示日志
-tf          # 显示日志
--tail num   # 要显示的记录条数
查看容器中的进程信息
# Windows系统环境
# 命令docker top 容器id
C:\cmder
λ docker top 0c7ee03d76dd
UID                 PID                 PPID                C                   STIME               TTY
TIME                CMD
root                5113                5092                0                   13:49               ?
00:00:00            /bin/sh -c while true;do echo bruce_liu;sleep 1;done
root                13416               5113                0                   14:01               ?
00:00:00            /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1

查看镜像的元数据
docker inspect --help
# 命令
docker inspect 容器id

# 测试
C:\cmder
λ docker inspect 0c7ee03d76dd   # 
[
    {
        "Id": "0c7ee03d76ddc6dd4c8caea4a639bcbd191309f1f6794c223bb62958f05e13cc",
        "Created": "2022-01-05T13:49:27.0383541Z",
        "Path": "/bin/sh",
        "Args": [
            "-c",
            "while true;do echo bruce_liu;sleep 1;done"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 5113,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2022-01-05T13:49:27.6480989Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6",
        "ResolvConfPath": "/var/lib/docker/containers/0c7ee03d76ddc6dd4c8caea4a639bcbd191309f1f6794c223bb62958f05e13cc/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/0c7ee03d76ddc6dd4c8caea4a639bcbd191309f1f6794c223bb62958f05e13cc/hostname",
        "HostsPath": "/var/lib/docker/containers/0c7ee03d76ddc6dd4c8caea4a639bcbd191309f1f6794c223bb62958f05e13cc/hosts",
        "LogPath": "/var/lib/docker/containers/0c7ee03d76ddc6dd4c8caea4a639bcbd191309f1f6794c223bb62958f05e13cc/0c7ee03d76ddc6dd4c8caea4a639bcbd191309f1f6794c223bb62958f05e13cc-json.log",
        "Name": "/brave_cartwright",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "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": [
                30,
                120
            ],
            "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/24d07c55a599d8b51e7035d22fd8d1825e132552271702bc42c1410417e22a01-init/diff:/var/lib/docker/overlay2/88853f06c6da7ba74b65019d6f86fcff4301dba97631a2cdd7ebe466cbc3cc0f/diff",
                "MergedDir": "/var/lib/docker/overlay2/24d07c55a599d8b51e7035d22fd8d1825e132552271702bc42c1410417e22a01/merged",
                "UpperDir": "/var/lib/docker/overlay2/24d07c55a599d8b51e7035d22fd8d1825e132552271702bc42c1410417e22a01/diff",
                "WorkDir": "/var/lib/docker/overlay2/24d07c55a599d8b51e7035d22fd8d1825e132552271702bc42c1410417e22a01/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [],
        "Config": {
            "Hostname": "0c7ee03d76dd",
            "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/sh",
                "-c",
                "while true;do echo bruce_liu;sleep 1;done"
            ],
            "Image": "centos",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.label-schema.build-date": "20210915",
                "org.label-schema.license": "GPLv2",
                "org.label-schema.name": "CentOS Base Image",
                "org.label-schema.schema-version": "1.0",
                "org.label-schema.vendor": "CentOS"
            }
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "325904a8305da35e3bccb874c66331dceabb2fb0917e0e5f364ec144dac6d891",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {},
            "SandboxKey": "/var/run/docker/netns/325904a8305d",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "ca20615b2260f60d00b7a801466257e4cf180d6a9cc51ca5b7fe1a31fb5a0241",
            "Gateway": "172.17.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:02",
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "bc7d4b7e5df6399b894535936e96884d6f4fd226f10bd0118f2d8293f8df5fc6",
                    "EndpointID": "ca20615b2260f60d00b7a801466257e4cf180d6a9cc51ca5b7fe1a31fb5a0241",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
        }
    }
]
进入当前正在运行的容器
# 我们通常容器都使用后台方式运行的,需要进入容器,修改一些配置
# 命令
docker exec  -it 容器id bashShell
C:\cmder
λ docker exec -it 0c7ee03d76dd /bin/bash
[root@0c7ee03d76dd /]# pwd
/
[root@0c7ee03d76dd /]# clear
bash: clear: command not found
[root@0c7ee03d76dd /]# 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 attach --help
# 测试
C:\cmder
λ docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS     NAMES
0c7ee03d76dd   centos    "/bin/sh -c 'while t…"   44 minutes ago   Up 44 minutes             brave_cartwright

C:\cmder
λ docker attach 0c7ee03d76dd
bruce_liu
bruce_liu
bruce_liu
bruce_liu
正在执行当前的代码......
# docker exec      ---------进入容器后开启一个新的终端,可以在里面操作(常用)
# docker attach    ---------进入容器正在执行的终端,不会启动新的进程!
从容器内拷贝文件到主机上
docker cp 容器id:容器内路径 目的地主机路径
docker cp 容器id:路径/文件  目的主机路径
# 进入docker容器内部
docker attach 容器id
# 在容器内执行命令 touch test.java
# 然后执行exit, 退出容器
# 将这个文件拷贝出来的到主机上
docker cp 容器id:/test.java c:\

# 拷贝是一个手动过程,未来我们使用 -v 卷的技术,可以实现
学习方式:将所有命令全部敲一遍,自己记录 笔记

小结:

attach   Attach to a running container			           # 当前shell下attach连接指定运行镜像
build 	 Build an image from  a Dockerfile 		            # 通过Dockerfile 定制镜像
commit 	 Create a new image from a container changes        # 提交当前容器为新的镜像
cp       Copy files/folders from the containers filesystem to the host path       # 从容器中拷贝指定文件或者目录到宿主机
create   Create a new container 							# 创建一个新的容器, 同run ,但不启动容器
diff 	 Inspect changes on a container's filesystem           # 查看docker容器变化
events   Get real time events from the server				# 从docker服务获取容器实时事件
exec	 Run  a command in an existing container    			# 在已存在的容器上运行命令
export	 Stream the contents of a container as a tar archive      # 导出容器的内容流作为一个tar,归档文件[对应import]
history	 Show the history of an image 							# 展示一个镜像形成历史
images	 List images 										# 列出系统当前镜像
import   Create a new filesystem image from the contents of a tarball  # 从tar包中的内容创建一个新的文件系统映像[对应export]
info	 Display system-wide information					# 显示系统相关信息
inspect  Return low-level information on a container   		  # 查看容器详细信息
kill 	 Kill a running container 							# kill 指定的docker 容器
load	 Load an image from a tar archive					# 从一个tar包中加载一个镜像[对应save]
login	 Register or Login to the docker registry server        # 注册或者登录一个docker源服务器
logout 	 Log out from a Docker registry server 				 # 从当前docker registry退出
logs 	 Fetch the logs of a container						# 输出当前容器日志信息
port 	 Lookup the public-facing port which is NAT-ed to PRIVATE_PORT   # 查看映射端口对应的容器内部源端口
pause     Pause all processs within a container				 # 暂停容器
ps 		 List containers 								   # 列出容器列表
pull 	 Pull an image or a repository from the docker registry server   # 从docker镜像源服务器拉取指定镜像或者镜像库
push  	 Push an image or a repository to the docker registry server     # 推送指定镜像或者库镜像至docker 源服务器
restart  Restart a running container 						# 重启运行的容器
rm 		 Remove one or more containers						# 移除一个或者多个容器
rmi 	 Remove one or more images				# 移除一个或者多个镜像[无容器使用该镜像才可删除,否则删除相关容器才可继续或-f 强制删除]
run 	 Run a command in a new container 		 # 创建一个新的容器并运行一个命令
save	 Save an image to a tar archive			 # 保存一个镜像为一个tar包(对应load)
search 	  Search for an image on the Docker Hub		# 在docker hub中搜索镜像
start     Start a stopped containers 			 # 启动容器
stop	 Stop a running containers 				 # 停止容器
tag 	 Tag an image into a repository 		  # 给源中镜像打标签
unpause	  Unpause a paused container 			  # 取消暂停容器
version   Show the docker version information 	   # 查看docker版本号
wait 	 Block until a  container stops, then print its exit code    # 截取容器停止时的退出状态值

作业练习:

Docker 安装nginx

# 搜索镜像,建议去docker hub网站搜索,这样可以看到很多帮助文档信息
# https://hub.docker.com/search?q=nginx&type=image&operating_system=linux
[root@localhost docker]# docker search ngnix
NAME                                   DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
userxy2015/ngnix                       ngnix                                           12                   
merpso/ngnix-plus-k8s-ingress          NGNIX+ kubernetes-ingess                        2                    
ludwringliccien/ngnix-php7.1           ngnix-php7.1                                    1                    [OK]
jhuiting/ngnix                                                                         1                    
sushanth53/ngnix_server                ngnix server                                    0                    

# 下载镜像
[root@localhost docker]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
a2abf6c4d29d: Pull complete 
a9edb18cadd1: Pull complete 
589b7251471a: Pull complete 
186b1aaa4aa6: Pull complete 
b4df32aa5a72: Pull complete 
a0bcbecc962e: Pull complete 
Digest: sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest

启动nginx

# 启动nginx ,-d 后台运行,--name为容器命名,-p 指定一个宿主机端口3344映射容器端口80 
[root@localhost docker]# docker run -d --name nginx01 -p 3344:80 nginx
0b32d7af3fac83f167050ae25787721467086185c376e46cc5a9cdbfcb5e823a

# 本机访问nginx
[root@localhost docker]# curl localhost:3344
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
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>

# 进入容器
[root@localhost docker]# docker exec -it nginx01 /bin/bash
root@0b32d7af3fac:/# wherei s nginx
bash: wherei: command not found
root@0b32d7af3fac:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@0b32d7af3fac:/# cd /etc/nginx/
root@0b32d7af3fac:/etc/nginx# ls
conf.d	fastcgi_params	mime.types  modules  nginx.conf  scgi_params  uwsgi_params

端口暴露的概念

-p 3344:80 # 3344宿主机端口 80 容器内端口

思考题:我们每次改动nginx配置文件,都需要进入容器内部?麻烦,如何在容器外部提供一个映射路径,达到在容器内修改文件名,容器内自动修改。

-v 数据卷

docker 安装一个tomcat

# 官方的使用
[root@localhost]$sudo docker run -it --rm tomcat:9.0

# 我们之前的启动都是后台,停止了容器之后,容器可以查到,docker run -it --rm 一般用来测试,用完即删

# 下载之后启动
[root@localhost]#docker pull tomcat

# 启动运行
[root@localhost]# dockerrun -d -p 3355:8080 --name tomcat01 tomcat

# 测试访问
http://172.16.12.154:3355
# 进入容器
[root@localhost]# docker exec -it  tomcat01 /bin/bash

# 发现问题
1.linux命令少了
2.没有webapps,解决办法:从webapps.dist文件夹下的所有文件拷贝到webapps文件夹下,或者直接修改webapps.dis名字
3.阿里云镜像的原因,默认是最小的镜像,所有不必要的都省略了。保证最小可运行的环境。
思考题
1.我们部署项目,如果每次都要进入容器很麻烦,我们可以在容器外部提供一个映射路径,webapps,我们在外部部署项目,就自动同步到内部就好了。

作业:部署es+kibana

# es 暴露的端口很多
# es 消耗内存资源
# es 的数据一般需要放置到安全目录,挂载
# --net somenetwork ? 网络配置
# 启动elasticsearch
$ docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:tag
# 启动了 linux卡住了 docker stats查看cpu的状态
# es 十分消耗内存
# 测试一下es是否成功
[root@localhost ~]# curl localhost:9200
{
  "name" : "5506ccc49024",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "838u-pJUScaq1g3sKs21ZQ",
  "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"
}

# 增加内存的限制,修改配置文件 -e 环境配置修改 , 64m最小  512m最大
[root@localhost ~]# docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2

作业:使用kibana连接elasticsearch

可视化


  • portainer(先用这个)
[root@localhost ~]# docker run -d -p 8088:9000 \ 
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
  • Rancher(CI/CD再用)

    什么是portainer?

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

[root@localhost ~]# docker run -d -p 8088:9000 \ 
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
访问测试:外网8088

http://ip:8088

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G6EycbiA-1641913771905)(http://localhost:8088/5da83cfb4883a59354abeff852cb7394.png)]

可视化面板平时不会使用,可以测试玩玩。

Docker镜像讲解:

镜像是什么?

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

所有应用,直接打包docker镜像,可以直接运行、部署。

如何得到镜像:

  • 从远程仓库下载
  • 从别人那拷贝过来
  • 自己之作一个镜像DockerFile文件

Docker镜像加载原理

UnionFS(联合文件系统)

我们下载的时候看到的一层一层就是这个。

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

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

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

黑屏—加载—开机进入系统

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

虚拟机是分钟级启动,容器是秒级。

分层理解

理解:

所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。例如:基于Ubuntu Linux 16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。

特点:

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

commit镜像

docker commit 提交容器成为一个新的副本
# 命令和git原理类似
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]

实战测试

# 1、启动一个默认的tomcat
# 2、发现这个默认的tomcat没有webapps应用,镜像的原因,官方的镜像默认是webapps下面没有任何文件的
# 3、然后我们从webapps.dist文件夹拷贝过去
# 4、将我们操作过的容器通过commit提交为一个镜像,以后我们就直接使用这个修改过的镜像即可。如下图:

理论联系实际,切记要实际操作一下!

#如果想要保存当前容器的状态,就可以通过commit来提交,获得一个新的镜像。我的理解类似于vm快照功能。

容器数据卷


什么是容器数据卷


docker的理念回顾

将应用和环境打包成一个镜像。

如果数据都在容器中,那么容器删除,数据就会丢失!需求:数据可以长久化,MySQL,容器删了,删库跑路。=需求:MySQL数据可以存储在本地=

容器之间可以有一个数据共享技术!Docker容器中产生的数据,同步到本地。这就是卷技术,目前的挂载,将我们容器内的目录,挂载到Linux上面。

总结:容器的持久化和同步操作,容器间也可以数据共享。

使用数据卷

# 方式一:直接使用命令挂载 -v
docker run -it -v 主机目录:容器内目录
# 测试
root@liuxiaoweideAir ~ # docker run -it -v /Users/liuxiaowei/ceshi:/home centos /bin/bash  #主机目录:/Users/liuxiaowei/ceshi 容器目录:/home 
# 启动之后,通过docker inspect 容器id 检验卷如何挂载
root@liuxiaoweideAir liuxiaowei # docker inspect 3af3cfc435c3
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/Users/liuxiaowei/ceshi",   # 主机内地址
                "Destination": "/home",                # docker 容器内的地址
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ]

测试文件的同步效果如图:
逆向测试

1、退出容器

2、然后在宿主机目录下进行操作

3、再启动容器

4、查看容器内目录文件同步变化

优点:以后修改只需在本地修改即可,容器内会自动同步。

实战:安装MySQL

思考:MySQL的数据持久化的问题
# 获取镜像
root@liuxiaoweideAir ~ # docker pull mysql:5.7
# 运行容器,需要做数据挂载, 安装启动mysql,需要配置密码的,这需要注意。去https://hub.docker.com/搜索mysql
# Start a mysql server instance
# Starting a MySQL instance is simple:
$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
# 启动容器
-d 后台运行
-p 端口映射
-v 卷挂载 (两个-v 挂载两个目录)
-e 环境配置
--name 容器名字
root@liuxiaoweideAir ~ # docker run -d -p 3310:3306 -v /Users/liuxiaowei/mysql/conf:/etc/mysql/conf.d -v /Users/liuxiaowei/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456  --name mysql01 mysql:5.7
42053d1fb7043624bb199b7f5d876ccd2299d5047230cee847a4dcabb5657ddf

# 启动成功之后,利用Navicat或者SQL PRO连接测试,连接到服务器的3310 --- 3310和容器内的3306映射。如下图

# 在本地测试创建一个数据库,查看一下我们映射的路径是否同步。
本例:root@liuxiaoweideAir data # ls
auto.cnf		ib_logfile1		server-cert.pem
ca-key.pem		ibdata1			server-key.pem
ca.pem			ibtmp1			sys
client-cert.pem		mysql			test # 在mysql容器里建立的数据库
client-key.pem		performance_schema	test1 # 在mysql容器里建立的数据库
ib_buffer_pool		private_key.pem
ib_logfile0		public_key.pem
root@liuxiaoweideAir data # pwd
/Users/liuxiaowei/mysql/data

假设我们将容器删除

root@liuxiaoweideAir data # docker rm -f mysql01
mysql01
root@liuxiaoweideAir data # docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

root@liuxiaoweideAir data # ls
auto.cnf		ib_logfile0		public_key.pem
ca-key.pem		ib_logfile1		server-cert.pem
ca.pem			ibdata1			server-key.pem
client-cert.pem		mysql			sys
client-key.pem		performance_schema	test
ib_buffer_pool		private_key.pem		test1

发现,我们挂载到本地的数据卷依旧没有丢失,这就实现了容器数据持久化功能!

具名和匿名挂载

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

# 查看所有的卷的信息
root@liuxiaoweideAir liuxiaowei # docker volume ls    
DRIVER    VOLUME NAME
local     3e8ab2696b7005a359de2bdaf5fc70a01881652fc0a789b3dcbac3d12b42a841   # 匿名

# 具名挂载nginx "juming-nginx"
root@liuxiaoweideAir liuxiaowei # docker run -d -P --name nginx02 -v juming-nginx:/ect/nginx nginx
df397dd0401dc1f2904671efaeca9749c7813fca846ba097f890666785094327
root@liuxiaoweideAir liuxiaowei # docker volume ls
DRIVER    VOLUME NAME
local     f40d828c9c069666740ff54f90c35e6061071cf684198ca5c2e9caab7871fdf0
local     juming-nginx   # 具名
local     vsCodeServerVolume-liuxiaowei-recursing_leakey

# 查看一下这个具名卷
root@liuxiaoweideAir liuxiaowei # docker volume inspect juming-nginx
[
    {
        "CreatedAt": "2022-01-08T14:24:41Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data",  # 挂载点
        "Name": "juming-nginx",
        "Options": null,
        "Scope": "local"
    }
]
所有的docker容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volumes/xxxx/_data

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

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

拓展:

# 通过 -v 容器内路径:ro rw 改变读写权限
ro  --- readonly    # 只读
rw  --- readwrite   # 可读可写
# 一旦设置了容器权限,容器对我们挂载出来的内容就有限定
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

# ro 说明这个路径只能通过宿主机来操作,容器内部无法操作

初识Dockerfile


Dockerfile 就是用来构建docker镜像的构建文件,就是一个命令脚本,通过这脚本可以生成镜像,镜像是一层一层的,脚本就是一个个的命令,

# 创建一个dockerfile文件,名字可以随意,建议用dockerfile
# 文件中内容,指令都是大写,参数
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "---end----"
CMD /bin/bash

# 这里的每个命令就是镜像的一层
**本人的理解类似于windows系统的批处理文件**

root@liuxiaoweideAir docker-test-volume # docker build -f /Users/liuxiaowei/docker-test-volume/dockerfile1 -t  bruceliu/centos:1.0 .
[+] Building 1.6s (5/5) FINISHED                                                
 => [internal] load build definition from dockerfile1                      0.5s
 => => transferring dockerfile: 120B                                       0.0s
 => [internal] load .dockerignore                                          0.5s
 => => transferring context: 2B                                            0.0s
 => [internal] load metadata for docker.io/library/centos:latest           0.0s
 => [1/1] FROM docker.io/library/centos                                    0.4s
 => exporting to image                                                     0.1s
 => => exporting layers                                                    0.0s
 => => writing image sha256:9ec777f9328b3414e208ee19b30072b218f5c6bfb152a  0.0s
 => => naming to docker.io/bruceliu/centos:1.0                             0.0s

Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
root@liuxiaoweideAir docker-test-volume # ls
dockerfile1

# 启动该容器
root@liuxiaoweideAir liuxiaowei # docker images
REPOSITORY                        TAG                                        IMAGE ID       CREATED         SIZE
tomcat01                          1.0                                        3694687aedfe   20 hours ago    684MB
nginx                             latest                                     605c77e624dd   10 days ago     141MB
tomcat                            9.0                                        b8e65a4d736d   2 weeks ago     680MB
tomcat                            latest                                     fb5657adc892   2 weeks ago     680MB
mysql                             5.7                                        c20987f18b13   2 weeks ago     448MB
docker/getting-started            latest                                     26d80cd96d69   5 weeks ago     28.5MB
ubuntu                            latest                                     ba6acccedd29   2 months ago    72.8MB
centos                            latest                                     5d0da3dc9764   3 months ago    231MB
bruceliu/centos                   1.0                                        9ec777f9328b   3 months ago      231MB  # dockerfile生成的镜像
docker/dev-environments-default   stable-1                                   7c85b0303242   5 months ago    607MB
docker/desktop-git-helper         5a4fca126aadcd3f6cc3a011aa991de982ae7000   efe2d67c403b   5 months ago    44.2MB
portainer/portainer               latest                                     580c0e4e98b0   9 months ago    79.1MB
scrapinghub/splash                latest                                     9364575df985   16 months ago   1.89GB
ubuntu                            15.10                                      9b9cb95443b5   5 years ago     137MB
training/webapp                   latest                                     6fae60ef3446   6 years ago     349MB
root@liuxiaoweideAir liuxiaowei # docker run -it 9ec777f9328b /bin/bash
[root@6c7b9856d5de /]# ls
bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var	   volume02
dev  home  lib64  media       opt  root  sbin  sys  usr  volume01

这两个卷和外部一定有一个是 和外部同步的目录

FROM centos
VOLUME ["volume01","volume02"]  # 匿名挂载
CMD echo "----end----"

# 查看一下卷挂载的路径
docker inspect 容器id    
"Mounts": [
            {
                "Type": "volume",
                "Name": "7b40488c0291a9cc8858a2b831fc11e24807b66794fbcb5e0130fd28eb97955d",
                "Source": "/var/lib/docker/volumes/7b40488c0291a9cc8858a2b831fc11e24807b66794fbcb5e0130fd28eb97955d/_data",
                "Destination": "volume01",  # 对应匿名卷
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "2a9464346288b8be9bc62743b05aa3cb1652c7167afad3847e0c617027a00847",
                "Source": "/var/lib/docker/volumes/2a9464346288b8be9bc62743b05aa3cb1652c7167afad3847e0c617027a00847/_data",
                "Destination": "volume02",  # 对应匿名卷
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation
}
]

在此提个问题,也是我遇到的 ,这个挂载卷路径在mac系统是不存在的,通过查阅资料,有一种解决方法就是更新docker之后,然后执行screen 路径,就可以了。但是我尝试了还是不行。

不过在centos环境,不存在这个问题

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

数据卷容器


多个mysql同步数据

# 启动3个容器,通过我们自己写的脚本生成的镜像bruceliu/centos:1.0启动,下面是在centos7环境执行
[root@localhost]# docker run -it --name docker01 bruceliu/centos:1.0.  

# 启动第二个容器继承docker01
[root@localhost]# docker run -it --name docker02 --volumes-from docker01 bruceliu/centos:1.0

Docker01 创建文件docker01同步到docker02里面的volume01,如图:

# 只要通过--volumes-from就可以实现容器间的数据共享

# 测试:可以删除docker01,查看一下docker02和docker03是否还可以访问这个文件 。结果是可以的。

多个mysql实现数据共享

root@liuxiaoweideAir ~ # docker run -d -p 3310:3306 -v /Users/liuxiaowei/mysql/conf:/etc/mysql/conf.d -v /Users/liuxiaowei/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456  --name mysql01 mysql:5.7

root@liuxiaoweideAir ~ # docker run -d -p 3310:3306  -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7 

# 可以实现两个容器数据同步

结论:

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

但是一旦持久化到了本地,这个时候,本地的数据是不会被删除的

DockerFile


DockerFile的介绍

dockerfile 是用来构建docker镜像的文件,命令参数脚本。
构建步骤:
1、编写一个dockerfile文件
2、docker build 构建成一个镜像
3、docker run 运行镜像
4、docker push 发布镜像(DockerHub、阿里云镜像仓库 )

查看一下官网是怎么做的?

很多官方镜像都是基础包,很多功能没有。

我们自己的镜像文件可以根据需求构建

dockerfile的命令,通过百度搜索图片。“dockerfile命令”

DockerFile构建过程

基础知识:
1、每个保留关键字(指令)都是必须大写字母
2、指令从上到下顺序执行
3、# 表示注释
4、每一个指令都会创建提交一个新的镜像层,并提交。

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

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

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

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

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

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

DockerFile指令


1、知道这些指令后, 我们可以自己构建镜像。

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

实战测试


1、Docker Hub 中99%镜像都是从这个基础镜像开始,FROM scratch(白手起家,从头做起),然后配置需要的软件和配置进行构建。

# 自己创建一个centos
# 1.编写Dockerfile文件 
FROM centos
MAINTAINER   bruce_liu<1134593154@qq.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

# 2.通过这个dockerfile文件构建镜像
# 命令docker build -f dockerfile文件路径 -t 镜像名:[tag] .
# 3.测试运行
[root@31a3aaa44ff1 local]# ifconfig     # 对比之前的原生centos,可以执行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 946 (946.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

# docker history 容器id   可以显示镜像的形成过程
root@liuxiaoweideAir dockerfile#docker history c20987f18b13

2、通过这个命令,我们可以研究一下别的镜像怎么生成的。
3、CMD和ENTRPOINT区别
CMD				# 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT		# 指定这个容器的时候要运行的命令,可以追加命令
4、测试CMD
root@liuxiaoweideAir dockerfile # vim dockerfile-cmd-test
FROM centos
CMD ["ls","-a"]

root@liuxiaoweideAir dockerfile # docker build -f dockerfile-cmd-test -t cmd-test .  # 通过dockerfile-cmd-test构建镜像
[+] Building 1.1s (5/5) FINISHED                                                                                                               
 => [internal] load build definition from dockerfile-cmd-test                                                                             0.3s
 => => transferring dockerfile: 76B                                                                                                       0.0s
 => [internal] load .dockerignore                                                                                                         0.4s
 => => transferring context: 2B                                                                                                           0.0s
 => [internal] load metadata for docker.io/library/centos:latest                                                                          0.0s
 => CACHED [1/1] FROM docker.io/library/centos                                                                                            0.0s
 => exporting to image                                                                                                                    0.1s
 => => exporting layers                                                                                                                   0.0s
 => => writing image sha256:7d202bdf002be182b794b7f2b4c90c4fe3560c3ac4f8cebc27f1c8a94ab10a9a                                              0.0s
 => => naming to docker.io/library/cmd-test                                                                                               0.0s

Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
root@liuxiaoweideAir dockerfile # docker run -it cmd-test     # 通过dockerfile-cmd-test构建镜像,直接执行最后一个CMD,“ls -a”
.   .dockerenv	dev  home  lib64       media  opt   root  sbin	sys  usr
..  bin		etc  lib   lost+found  mnt    proc  run   srv	tmp  var
root@liuxiaoweideAir dockerfile # 

# 想追加一个命令 -l ,也就是我们希望执行ls -al
root@liuxiaoweideAir dockerfile # docker run cmd-test -l
docker: 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.
ERRO[0002] error waiting for container: context canceled 

# 出现这个错误提示,因为CMD的情况下,-l替换了CMD ["ls","-a"]命令,-l不是完整命令,所以报错
# 如下用ls -al 完整命令替换,就不会报错
root@liuxiaoweideAir dockerfile # docker run cmd-test ls -al   
total 56
drwxr-xr-x   1 root root 4096 Jan  9 11:15 .
drwxr-xr-x   1 root root 4096 Jan  9 11:15 ..
-rwxr-xr-x   1 root root    0 Jan  9 11:15 .dockerenv
lrwxrwxrwx   1 root root    7 Nov  3  2020 bin -> usr/bin
drwxr-xr-x   5 root root  340 Jan  9 11:15 dev
drwxr-xr-x   1 root root 4096 Jan  9 11:15 etc
drwxr-xr-x   2 root root 4096 Nov  3  2020 home
lrwxrwxrwx   1 root root    7 Nov  3  2020 lib -> usr/lib
lrwxrwxrwx   1 root root    9 Nov  3  2020 lib64 -> usr/lib64
drwx------   2 root root 4096 Sep 15 14:17 lost+found
drwxr-xr-x   2 root root 4096 Nov  3  2020 media
drwxr-xr-x   2 root root 4096 Nov  3  2020 mnt
drwxr-xr-x   2 root root 4096 Nov  3  2020 opt
dr-xr-xr-x 170 root root    0 Jan  9 11:15 proc
dr-xr-x---   2 root root 4096 Sep 15 14:17 root
drwxr-xr-x  11 root root 4096 Sep 15 14:17 run
lrwxrwxrwx   1 root root    8 Nov  3  2020 sbin -> usr/sbin
drwxr-xr-x   2 root root 4096 Nov  3  2020 srv
dr-xr-xr-x  13 root root    0 Jan  9 11:15 sys
drwxrwxrwt   7 root root 4096 Sep 15 14:17 tmp
drwxr-xr-x  12 root root 4096 Sep 15 14:17 usr
drwxr-xr-x  20 root root 4096 Sep 15 14:17 var
5、测试ENTRYPOINT
# 构建entrypoint dockerfile 文件
root@liuxiaoweideAir dockerfile # vim dockerfile-cmd-entrypoint
FROM centos
ENTRYPOINT ["ls","-a"]
# 生成镜像文件
root@liuxiaoweideAir dockerfile # docker build -f dockerfile-cmd-entrypoint -t entry-centos .
[+] Building 1.0s (5/5) FINISHED                                                                                                   
 => [internal] load build definition from dockerfile-cmd-entrypoint                                                           0.2s
 => => transferring dockerfile: 90B                                                                                           0.0s
 => [internal] load .dockerignore                                                                                             0.3s
 => => transferring context: 2B                                                                                               0.0s
 => [internal] load metadata for docker.io/library/centos:latest                                                              0.0s
 => CACHED [1/1] FROM docker.io/library/centos                                                                                0.0s
 => exporting to image                                                                                                        0.1s
 => => exporting layers                                                                                                       0.0s
 => => writing image sha256:b325f5b972337e763ad3b2c0f1a720eb2d5b11a39b3d88008cc5a0e42393b617                                  0.0s
 => => naming to docker.io/library/entry-centos                                                                               0.0s

Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
root@liuxiaoweideAir dockerfile # docker images
REPOSITORY                        TAG                                        IMAGE ID       CREATED             SIZE
mycentos                          1.0                                        60d5f5ace1c7   About an hour ago   312MB
nginx                             latest                                     605c77e624dd   10 days ago         141MB
tomcat                            9.0                                        b8e65a4d736d   2 weeks ago         680MB
mysql                             5.7                                        c20987f18b13   2 weeks ago         448MB
docker/getting-started            latest                                     26d80cd96d69   5 weeks ago         28.5MB
ubuntu                            latest                                     ba6acccedd29   2 months ago        72.8MB
entry-centos                      latest                                     b325f5b97233   3 months ago        231MB

root@liuxiaoweideAir dockerfile # docker run -it b325f5b97233  # 运行 entrypoint生成的容器
.   .dockerenv	dev  home  lib64       media  opt   root  sbin	sys  usr
..  bin		etc  lib   lost+found  mnt    proc  run   srv	tmp  var
6、对比CMD
# 追击参数-l,正常执行,直接拼接ENTRYPOINT命令后面,没有报错
root@liuxiaoweideAir dockerfile # docker run -it b325f5b97233 -l   
total 56
drwxr-xr-x   1 root root 4096 Jan  9 11:36 .
drwxr-xr-x   1 root root 4096 Jan  9 11:36 ..
-rwxr-xr-x   1 root root    0 Jan  9 11:36 .dockerenv
lrwxrwxrwx   1 root root    7 Nov  3  2020 bin -> usr/bin
drwxr-xr-x   5 root root  360 Jan  9 11:36 dev
drwxr-xr-x   1 root root 4096 Jan  9 11:36 etc
drwxr-xr-x   2 root root 4096 Nov  3  2020 home
lrwxrwxrwx   1 root root    7 Nov  3  2020 lib -> usr/lib
lrwxrwxrwx   1 root root    9 Nov  3  2020 lib64 -> usr/lib64
drwx------   2 root root 4096 Sep 15 14:17 lost+found
drwxr-xr-x   2 root root 4096 Nov  3  2020 media

Dockerfile中很多命令都很相似,我们需要了解它们的区别,最好的学习方法就是对他们进行对比测试。

实战:Tomcat镜像


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

2、编写dockerfile 文件,官方命名Dockerfile, build 会自动寻找这个文件,就可以不需要-f指定了
# 在mac系统环境,能够执行
FROM centos
MAINTAINER bruce_liu<1134593154@qq.com>

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

ADD jdk-8u261-macosx-x64.dmg.zip /usr/local/
ADD apache-tomcat-9.0.56.tar.gz /usr/local/

RUN yum -y install vim

ENV MYPATH /usr/local
WORKDIR $MYPATH

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

EXPOSE 8080

CMD /usr/local/apache-tomcat-9.0.56/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.56/logs/catalina.out
# 在centos7系统测试
FROM centos
MAINTAINER bruce_liu<1134593154@qq.com>

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

ADD jdk-17_linux-x64_bin.tar.gz  /usr/local/
ADD apache-tomcat-8.5.33.tar.gz  /usr/local/


RUN yum -y install vim


ENV MYPATH /usr/local
WORKDIR $MYPATH

ENV JAVA_HOME /usr/local/jdk-17.0.1
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.33
ENV CATALINA_BASH /usr/local/apache-tomcat-8.5.33
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

EXPOSE 8080

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

3、构建镜像
# 由于是官方标准命名Dockerfile,所以不用添加参数-f 最后一定要加上.
# 在mac系统环境能够执行,正常生成镜像,但是按结尾提示执行docker scan会报错。
# 如果在centos7环境一切正常,目前没有找到解决办法
root@liuxiaoweideAir tomcat # docker build -t diytomcat .
[+] Building 83.8s (11/11) FINISHED                                                                                  
 => [internal] load build definition from Dockerfile                                                            0.3s
 => => transferring dockerfile: 681B                                                                            0.0s
 => [internal] load .dockerignore                                                                               0.4s
 => => transferring context: 2B                                                                                 0.0s
 => [internal] load metadata for docker.io/library/centos:latest                                                0.0s
 => CACHED [1/6] FROM docker.io/library/centos                                                                  0.0s
 => [internal] load build context                                                                              24.9s
 => => transferring context: 213.39MB                                                                          24.7s
 => [2/6] COPY readme.txt /usr/local/readme.txt                                                                 0.7s
 => [3/6] ADD jdk-8u261-macosx-x64.dmg.zip /usr/local/                                                          1.8s
 => [4/6] ADD apache-tomcat-9.0.56.tar.gz /usr/local/                                                           2.4s
 => [5/6] RUN yum -y install vim                                                                               44.7s
 => [6/6] WORKDIR /usr/local                                                                                    0.8s
 => exporting to image                                                                                          7.2s 
 => => exporting layers                                                                                         7.1s 
 => => writing image sha256:ab919c75922607c3239f6634b06651870d267a4a94589c82ccd319fda610b882                    0.0s 
 => => naming to docker.io/library/diytomcat                                                                    0.0s 
                                                                                                                     
Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
root@liuxiaoweideAir tomcat # docker images 
REPOSITORY                        TAG                                        IMAGE ID       CREATED              SIZE
diytomcat                         latest                                     ab919c759226   About a minute ago   527MB

# 在centos7测试
# 由于是官方标准命名Dockerfile,所以不用添加参数-f 最后一定要加上.
[root@localhost tomcat]# docker build -t diytomcat .
Sending build context to Docker daemon  190.3MB
Step 1/15 : FROM centos
 ---> 5d0da3dc9764
Step 2/15 : MAINTAINER bruce_liu<1134593154@qq.com>
 ---> Running in b22cb9028743
Removing intermediate container b22cb9028743
 ---> be05f2b3b86b
Step 3/15 : COPY readme.txt /usr/local/readme.txt
 ---> 1026e7aab5a8
Step 4/15 : ADD jdk-17_linux-x64_bin.tar.gz  /usr/local/
 ---> de54e65e0916
Step 5/15 : ADD apache-tomcat-8.5.33.tar.gz  /usr/local/
 ---> 5f002ff16d92
Step 6/15 : RUN yum -y install vim
 ---> Running in 2622ef5a0401
CentOS Linux 8 - AppStream                      4.3 MB/s | 8.4 MB     00:01
CentOS Linux 8 - BaseOS                         875 kB/s | 4.6 MB     00:05
CentOS Linux 8 - Extras                          13 kB/s |  10 kB     00:00
Dependencies resolved.
================================================================================
 Package             Arch        Version                   Repository      Size
================================================================================
Installing:
 vim-enhanced        x86_64      2:8.0.1763-16.el8         appstream      1.4 M
Installing dependencies:
 gpm-libs            x86_64      1.20.7-17.el8             appstream       39 k
 vim-common          x86_64      2:8.0.1763-16.el8         appstream      6.3 M
 vim-filesystem      noarch      2:8.0.1763-16.el8         appstream       49 k
 which               x86_64      2.21-16.el8               baseos          49 k
Transaction Summary
================================================================================
Install  5 Packages
Total download size: 7.8 M
Installed size: 30 M
Downloading Packages:
(1/5): gpm-libs-1.20.7-17.el8.x86_64.rpm        355 kB/s |  39 kB     00:00
(2/5): vim-filesystem-8.0.1763-16.el8.noarch.rp 1.1 MB/s |  49 kB     00:00
(3/5): vim-enhanced-8.0.1763-16.el8.x86_64.rpm  1.7 MB/s | 1.4 MB     00:00
(4/5): vim-common-8.0.1763-16.el8.x86_64.rpm    5.8 MB/s | 6.3 MB     00:01
(5/5): which-2.21-16.el8.x86_64.rpm              44 kB/s |  49 kB     00:01
--------------------------------------------------------------------------------
Total                                           2.1 MB/s | 7.8 MB     00:03
warning: /var/cache/dnf/appstream-02e86d1c976ab532/packages/gpm-libs-1.20.7-17.el8.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID 8483c65d: NOKEY
CentOS Linux 8 - AppStream                       66 kB/s | 1.6 kB     00:00
Importing GPG key 0x8483C65D:
 Userid     : "CentOS (CentOS Official Signing Key) <security@centos.org>"
 Fingerprint: 99DB 70FA E1D7 CE22 7FB6 4882 05B5 55B3 8483 C65D
 From       : /etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
Key imported successfully
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                        1/1
  Installing       : which-2.21-16.el8.x86_64                               1/5
  Installing       : vim-filesystem-2:8.0.1763-16.el8.noarch                2/5
  Installing       : vim-common-2:8.0.1763-16.el8.x86_64                    3/5
  Installing       : gpm-libs-1.20.7-17.el8.x86_64                          4/5
  Running scriptlet: gpm-libs-1.20.7-17.el8.x86_64                          4/5
  Installing       : vim-enhanced-2:8.0.1763-16.el8.x86_64                  5/5
  Running scriptlet: vim-enhanced-2:8.0.1763-16.el8.x86_64                  5/5
  Running scriptlet: vim-common-2:8.0.1763-16.el8.x86_64                    5/5
  Verifying        : gpm-libs-1.20.7-17.el8.x86_64                          1/5
  Verifying        : vim-common-2:8.0.1763-16.el8.x86_64                    2/5
  Verifying        : vim-enhanced-2:8.0.1763-16.el8.x86_64                  3/5
  Verifying        : vim-filesystem-2:8.0.1763-16.el8.noarch                4/5
  Verifying        : which-2.21-16.el8.x86_64                               5/5
Installed:
  gpm-libs-1.20.7-17.el8.x86_64         vim-common-2:8.0.1763-16.el8.x86_64
  vim-enhanced-2:8.0.1763-16.el8.x86_64 vim-filesystem-2:8.0.1763-16.el8.noarch
  which-2.21-16.el8.x86_64

Complete!
Removing intermediate container 2622ef5a0401
 ---> 57606bc79c81
Step 7/15 : ENV MYPATH /usr/local
 ---> Running in a2c900e33b46
Removing intermediate container a2c900e33b46
 ---> c536dc330700
Step 8/15 : WORKDIR $MYPATH
 ---> Running in 70aede458361
Removing intermediate container 70aede458361
 ---> a4757b245dd7
Step 9/15 : ENV JAVA_HOME /usr/local/jdk-17.0.1
 ---> Running in cbdbbd45a77d
Removing intermediate container cbdbbd45a77d
 ---> 29a5fec095c0
Step 10/15 : ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
 ---> Running in 44cc4bc03fff
Removing intermediate container 44cc4bc03fff
 ---> 7ee1d774dec6
Step 11/15 : ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.33
---> Running in 7aedcdacefca
Removing intermediate container 7aedcdacefca
 ---> d51a4835e53b
Step 12/15 : ENV CATALINA_BASH /usr/local/apache-tomcat-8.5.33
 ---> Running in c5545d41cfe0
Removing intermediate container c5545d41cfe0
 ---> 3ca740e8fb50
Step 13/15 : ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
 ---> Running in 11e9db1569cc
Removing intermediate container 11e9db1569cc
 ---> fa987bac62df
Step 14/15 : EXPOSE 8080
 ---> Running in c3f3b3bf9010
Removing intermediate container c3f3b3bf9010
 ---> a9f6ace395f0
Step 15/15 : CMD /usr/local/apache-tomcat-8.5.33/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.5.33/logs/catalina.out
 ---> Running in 5f8629ecaac4
Removing intermediate container 5f8629ecaac4
 ---> c5e5274bde3b
Successfully built c5e5274bde3b
Successfully tagged diytomcat:latest

4、启动镜像
# 在centos7环境成功
[root@localhost tomcat]#  docker run -d -p 9090:8080 --name bruceliutomcat -v /home/bruce_liu/build/tomcat/test:/usr/local/apache-tomcat-8.5.33/webapps/test -v /home/bruce_liu/build/tomcat/tomcatlogs:/usr/local/apache-tomcat-8.5.33/logs diytomcat
97d08b3ba87ae920cf3fdabfa6b03e9e827310b79c3e9f14db471a1ea65b499f
5、访问测试
6、发布项目(由于做了卷挂载,我们直接在本地编写项目就可以发布)
# 例如在test文件夹下建立WEB-INFO文件夹,然后编辑web.xml
<html>
  <body>
  <script>
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.open("GET","cd_catalog.xml",false);
xmlhttp.send();
xmlDoc=xmlhttp.responseXML;

document.write("<table border='1'>");
var x=xmlDoc.getElementsByTagName("CD");
for (i=0;i<x.length;i++)
{
document.write("<tr><td>");
document.write(x[i].getElementsByTagName("ARTIST")[0].childNodes[0].nodeValue);
document.write("</td><td>");
document.write(x[i].getElementsByTagName("TITLE")[0].childNodes[0].nodeValue);
document.write("</td></tr>");
}
document.write("</table>");
</script>


  </body>
</html>

# 在宿主机的test路径下建一个文件index.jsp
# 在外网访问成功
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Bruce_liu</title>
</head>
<body>
Hello Bruce_liu!<br/>
<%
out.println("你的 IP 地址 " + request.getRemoteAddr());
%>
</body>
</html>

结果:项目部署成功,可以直接访问!✌️

题外话:

假设以后搞开发,那么需要掌握Dockerfile的编写,所有项目一律都使用docker镜像发布运行!

发布自己的镜像


DockerHub

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

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

3、在这个服务器上提交自己的镜像

# centos7环境
root@localhost test]#  docker login --help

Usage:  docker login [OPTIONS] [SERVER]

Log in to a Docker registry.
If no server is specified, the default is defined by the daemon.

Options:
  -p, --password string   Password
      --password-stdin    Take the password from stdin
  -u, --username string   Username
 
 # 登录账号
[root@localhost test]# docker login -u bruceliu1973
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

4、登录完毕,可以提交镜像,执行docker push命令

# 在centos7环境执行,但是出现一个问题
[root@localhost test]# docker push diytomcat
Using default tag: latest
The push refers to repository [docker.io/library/diytomcat]
41597dc9883c: Preparing
ba91795798ac: Preparing
43b27989aa87: Preparing
9445929b0a14: Preparing
74ddd0ec08fa: Preparing
denied: requested access to the resource is denied

# 解决push镜像的问题
# 给镜像增加一个tag
# 语法,[root@localhost test]#docker tag 容器id username/imagename   *****username 是dockerhub用户名,imagename是镜像名, imagename一定跟要push的镜像名一样,否则还是被拒绝
[root@localhost test]# docker tag 66f61ab160f4 bruceliu1973/diytomcat:1.0

# 修改为username/imagename:tag格式,push成功,如下图
[root@localhost tomcat]# docker push bruceliu1973/diytomcat:1.0
The push refers to repository [docker.io/bruceliu1973/diytomcat]
41597dc9883c: Pushed
ba91795798ac: Pushed
43b27989aa87: Pushed
9445929b0a14: Pushed
74ddd0ec08fa: Pushed
1.0: digest: sha256:f37ddc8c0333224c1e5a98588469919bad63aa5632722977c56720718e6886f5 size: 1372

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

阿里云镜像服务

1、登录阿里云

2、找到容器镜像服务(https://cr.console.aliyun.com/cn-hangzhou/instances)

3、创建命名空间

4、创建容器镜像

5、浏览阿里云

点击仓库,看到里面有一些基本信息。

# 登录阿里云
[root@localhost ~]# docker login --username=bruce刘晓伟 registry.cn-hangzhou.aliyuncs.com
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.  # 宿主机这里存储用户名和密码,json文件未加密
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
# 登录成功以后,执行
[root@localhost ~]# docker tag[ImageId] registry.cn-hangzhou.aliyuncs.com/bruce_liu1973/bruce_liuxiaowei:[镜像版本号]
# 本例
[root@localhost ~]# docker tag[ImageId] registry.cn-  hangzhou.aliyuncs.com/bruce_liu1973/bruce_liuxiaowei:66f61ab160f4
# docker push,严格按照阿里云镜像推送命令格式执行,否则会被拒绝
[root@localhost ~]# docker push bruceliu1973/diytomcat:1.0  # 这个命令格式传DockerHub可以,传阿里云拒绝
# 按照阿里云格式推送到Registry,[镜像版本号]为上一步骤生成的版本号,此例为1.0,不是imageId
[root@localhost ~]# docker tag[ImageId] registry.cn-hangzhou.aliyuncs.com/bruce_liu1973/bruce_liuxiaowei:[镜像版本号] 
# 实际操作命令格式
[root@localhost ~]# docker push registry.cn-hangzhou.aliyuncs.com/bruce_liu1973/bruce_liuxiaowei:1.0

总结:阿里云容器镜像参考并严格按照官方文档格式执行命令。

以后如果想让自己的网站被大家访问,就可以把网站镜像发到阿里云或者DockerHub,然后大家pull—run— OK

小结:


镜像打包成一个tar压缩包,可以发送压缩包给别人,涉及到两个命令

[root@localhost ~]# docker save --help
Usage:  docker save [OPTIONS] IMAGE [IMAGE...]

Save one or more images to a tar archive (streamed to STDOUT by default)

Options:
  -o, --output string   Write to a file, instead of STDOUT

Docker 网络


理解Docker0


清空所有环境
# centos7系统环境
# 清空所有容器
[root@localhost ~]#docker rm -f $(docker ps -aq)
5b2b527d0cde
7f3c9bbc1a19
0153e509926d
d0184a7eb0ed
cb638941890b
1ce46e3625c8
31a3aaa44ff1
9ed360d184c0
1ac5ac579488

# 清除所有镜像
[root@localhost ~]# docker rmi -f $(docker images -aq)
Deleted: sha256:164e693bcb758292a0fc8b32b9c40d053d33eb3f5418b5a84a42f911a7121bb8
Untagged: mycentos:1.0
Deleted: sha256:60d5f5ace1c7cb9e3f882b494671a973f5a5dc6eb28479c30149fc3c796116b5
Untagged: nginx:latest
Untagged: nginx@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
Deleted: sha256:605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85
Deleted: sha256:b625d8e29573fa369e799ca7c5df8b7a902126d2b7cbeb390af59e4b9e1210c5
Deleted: sha256:7850d382fb05e393e211067c5ca0aada2111fcbe550a90fed04d1c634bd31a14
Deleted: sha256:02b80ac2055edd757a996c3d554e6a8906fd3521e14d1227440afd5163a5f1c4
Deleted: sha256:b92aa5824592ecb46e6d169f8e694a99150ccef01a2aabea7b9c02356cdabe7c
Deleted: sha256:780238f18c540007376dd5e904f583896a69fe620876cabc06977a3af4ba4fb5
Deleted: sha256:2edcec3590a4ec7f40cf0743c15d78fb39d8326bc029073b41ef9727da6c851f
Untagged: tomcat:9.0
Untagged: tomcat@sha256:cd96d4f7d3f5fc4d3bc1622ec678207087b8215d55021a607ecaefba80b403ea
Deleted: sha256:b8e65a4d736dca28cd65b1b3b18100aad2984fc9a484d423db7a8fcee1ed5d48
Deleted: sha256:7cea9b28ec076e69d2921f8fec7a6a0d40a815d8fc91a5ecfb7e817a0ae6d5cf

测试

# centos7系统环境
# 查看IP地址
1.lo:本机回环地址
2.ens33:阿里云内网地址
5.docker0:docker地址(可以想象为路由器),也是其他容器的gw
[root@localhost ~]# ip add
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:90:b4:23 brd ff:ff:ff:ff:ff:ff
    inet 172.16.12.154/24 brd 172.16.12.255 scope global noprefixroute dynamic ens33
       valid_lft 1499sec preferred_lft 1499sec
    inet6 fe80::20c:29ff:fe90:b423/64 scope link
       valid_lft forever preferred_lft forever
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:46:90:be brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever
4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN group default qlen 1000
    link/ether 52:54:00:46:90:be brd ff:ff:ff:ff:ff:ff
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:d4:3f:64:05 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:d4ff:fe3f:6405/64 scope link
       valid_lft forever preferred_lft forever
6: br-983a1a9b2f0f: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:dd:dd:3e:ce brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.1/16 brd 172.18.255.255 scope global br-983a1a9b2f0f
       valid_lft forever preferred_lft forever
       inet6 fe80::42:ddff:fedd:3ece/64 scope link
       valid_lft forever preferred_lft forever

三个网络

# 问题:docker 是如何处理容器网络访问的?
tomcat 容器 ----------> mysql 容器
# centos7系统环境
# 执行一个tomcat容器运行命令
[root@localhost ~]# docker run -d -P --name tomcat01 tomcat

# 查看容器的内部网络地址 ip addr
[root@localhost ~]# docker exec -it tomcat01 ip addr  
****如果出现报错提示****
[root@localhost ~]# docker exec -it tomcat01 ip addr
OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "ip": executable file not found in $PATH: unknown

# 按照如下方式解决
# 执行如下命令交互模式进入容器内
[root@localhost ~]# docker exec -it 6fde5463673b /bin/bash
root@6fde5463673b:/usr/local/tomcat# pwd
/usr/local/tomcat
# 在容器内安装iproute2
root@6fde5463673b:/usr/local/tomcat# apt update && apt install -y iproute2

Get:1 http://security.debian.org/debian-security bullseye-security InRelease [44.1 kB]
Get:2 http://deb.debian.org/debian bullseye InRelease [116 kB]
Get:3 http://deb.debian.org/debian bullseye-updates InRelease [39.4 kB]
Get:4 http://security.debian.org/debian-security bullseye-security/main amd64 Packages [102 kB]
Get:5 http://deb.debian.org/debian bullseye/main amd64 Packages [8183 kB]
Get:6 http://deb.debian.org/debian bullseye-updates/main amd64 Packages [2592 B]
Fetched 8487 kB in 3min 44s (37.9 kB/s)
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
All packages are up to date.
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  libatm1 libbpf0 libcap2 libcap2-bin libelf1 libmnl0 libpam-cap libxtables12
# 容器内安装ping命令
[root@localhost ~]# apt-get install iputils-ping
# 安装vim命令
[root@localhost ~]# apt-get install vim
#安装ifconfig命令
[root@localhost ~]#apt-get install net-tools

# 在容器内执行 ip addr,发现容器启动的时候会得到一个eth0@if18 ip地址,docker分配
[root@6fde5463673b:/usr/local/tomcat]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
17: eth0@if18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
 
# 思考:linux宿主机能不能ping通容器内部
# 在linux宿主机ping docker容器ip地址,结果如下,可以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=5.87 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.054 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.061 ms
--- 172.17.0.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 0.054/1.995/5.871/2.740 ms

原理

1、我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个默认网卡docker桥接模式,使用的技术是***veth-pair***技术,如图所示:

在centos7宿主机再次测试 ip addr

# 在宿主机linux环境执行,查看ip配置信息
[root@localhost ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:90:b4:23 brd ff:ff:ff:ff:ff:ff
    inet 172.16.12.154/24 brd 172.16.12.255 scope global noprefixroute dynamic ens33
       valid_lft 1654sec preferred_lft 1654sec
    inet6 fe80::20c:29ff:fe90:b423/64 scope link
       valid_lft forever preferred_lft forever
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:46:90:be brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever
4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN group default qlen 1000
		link/ether 52:54:00:46:90:be brd ff:ff:ff:ff:ff:ff
5: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:d4:3f:64:05 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:d4ff:fe3f:6405/64 scope link
       valid_lft forever preferred_lft forever
6: br-983a1a9b2f0f: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:dd:dd:3e:ce brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.1/16 brd 172.18.255.255 scope global br-983a1a9b2f0f
       valid_lft forever preferred_lft forever
    inet6 fe80::42:ddff:fedd:3ece/64 scope link
       valid_lft forever preferred_lft forever
# 启动一个容器,宿主机就会出现一对网卡
18: veth4f4cbe7@if17: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
    link/ether ca:17:c3:c0:51:6c brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::c817:c3ff:fec0:516c/64 scope link
       valid_lft forever preferred_lft forever

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

# 我们发现容器带来的网卡,都是成对出现
# veth-pari就是一对的虚拟设备接口,所有容器的指向一个共同网关,宿主机docker0
# OpenStac Docker容器之间的连接,OVS的连接,都是使用veth-pair技术

3、测试一下tomcat01和tomcat02是否ping通,完全可以,都在一个网段

结论:tomcat01和tomcat02是共用一个路由器docker0,所有的容器在不指定网络的情况下,都是有docker0转发。

Docker中的所有网络接口都是虚拟的,虚拟的转发效率高。(内网传递文件)

如果容器删除,对应的vets-pair对删除(veth-pair)

– Link


1、假设一个场景,我们编写了一个微服务,database url=ip:, 项目不重启,数据库ip换掉了,我们希望可以处理这个问题,可以用名字来进行访问容器?
# 直接这样执行是ping不通的
[root@localhost ~]# docker exec -it tomcat02 ping tomcat01
ping:tomcat01: No address associated with hostname

# 如何解决呢?
# 通过 --link即可以解决网络连通问题
[root@localhost ~]# docker run -d -P --name tomcat03 --link tomcat02 tomcat
3e5adcd4d5b5e4b488f6f68747c21886d157e3518180d8109d607b2de8281d21
[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=24.5 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.074 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=3 ttl=64 time=0.098 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=4 ttl=64 time=0.078 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=5 ttl=64 time=0.075 ms

# 反向可以ping通吗?
[root@localhost ~]# docker exec -it tomcat02 ping tomcat03
ping:tomcat03: No address associated with hostname                                                    
2、探究: 利用inspect
# 在centos系统环境执行如下命令
# 第一行是docker0
[root@localhost ~]# docker network ls
NETWORK ID     NAME                                  DRIVER    SCOPE
f0252b7d323e   bridge                                bridge    local
4d03c52372e1   host                                  host      local
898465300bee   none                                  null      local
983a1a9b2f0f   x34-arbitrary-file-deletion_default   bridge    local

# 然后执行docker network inspect [NETWORK ID]
[root@localhost ~]# docker network inspect f0252b7d323e
[
    {
        "Name": "bridge",
        "Id": "f0252b7d323ed587414479e7c9500efe84a011bee1fc745674a6193fc2147874",
        "Created": "2022-01-09T15:16:02.834596925-05:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",    # 默认docker0
            "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": {
            "2923494636b68c0208e750a5617387899a50ac8ff5f59a139d2e1b3d49f9725e": {
                "Name": "tomcat01",
                "EndpointID": "8b947e54e960868ec731fb26371916b20d5f1fe9e583b5b4fd05359d58b504bb",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",    # 每启动一个容器,不指定ip,容器就会随机分配一个IP
                "IPv6Address": ""
						 },
            "3e5adcd4d5b5e4b488f6f68747c21886d157e3518180d8109d607b2de8281d21": {
                "Name": "tomcat03",
                "EndpointID": "186c9a43a4ca47d8603e5487c6f909fc5490b2bdb9456d719d230cc592e6df4c",
                "MacAddress": "02:42:ac:11:00:04",
                "IPv4Address": "172.17.0.4/16",   # 每启动一个容器,不指定ip,容器就会随机分配一个IP
                "IPv6Address": ""
            },
            "fc4aa0be8b52ff3967ad44a5e6678e194767f26e1fd3840d9e2b1340fa24e1df": {
                "Name": "tomcat02",
                "EndpointID": "872b06c64cbca78d15d3a0fb5f4b559e5fe02cb649a86020d40a1f20e2838948",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",  # 每启动一个容器,不指定ip,容器就会随机分配一个IP
                "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": {}
    }
]

其实这个tomcat03就是在本地配置了tomcat02的配置

# 查看hosts配置,在这里可以发现原理。
[root@localhost ~]# docker exec -it 3e5adcd4d5b5 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 fc4aa0be8b52 # 在 tomcat03的hosts配置里172.17.0.3 ---->tomcat02映射
172.17.0.4      3e5adcd4d5b5  # tomcat03

本质:–link就是我们在hosts配置里增加了一条172.17.0.3 tomcat02 fc4aa0be8b52映射

真实操作场景,已经***不建议***使用–link了!!

自定义网络,***不适用***docker0!

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

自定义网络


查看所有的docker网络
[root@localhost ~] # docker network ls
NETWORK ID     NAME                                  DRIVER    SCOPE
f0252b7d323e   bridge                                bridge    local
4d03c52372e1   host                                  host      local
898465300bee   none                                  null      local
983a1a9b2f0f   x34-arbitrary-file-deletion_default   bridge    local
网络模式
1、Bridge : 桥接 docke 0.1 0.2 0.3 都通过桥转发(默认使用模式)
2、none :不配置网络
3、host : 主机模式,和宿主机共享网络
4、container : 容器网络连通(局限性大)
测试

清空网络容器

[root@localhost ~]#docker rm -f $(docker ps -aq)

# 直接启动的命令 --net bridge, 这个就是docker0
[root@localhost ~] # docker run -d -P --name tomcat01  tomcat   # 原来的启动方式
[root@localhost ~] # docker run -d -P --name tomcat01 --net bridge tomcat   # 默认


# docker0特点:默认,域名不能访问, --link可以打通连接
# 我们可以自定义网络
# --driver bridge
# --subnet 192.168.0.0/24
# --gateway 192.168.0.1
[root@localhost ~]# docker network create --driver bridge --subnet 192.168.0.0/24 --gateway 192.168.0.1 mynet
3fa16a661c63da775336a98aadba1447d69e01009f5afbf2e38f2bbb0cdf669d

[root@localhost ~]# docker network ls
NETWORK ID     NAME                                  DRIVER    SCOPE
f0252b7d323e   bridge                                bridge    local
4d03c52372e1   host                                  host      local
3fa16a661c63   mynet                                 bridge    local
898465300bee   none                                  null      local
983a1a9b2f0f   x34-arbitrary-file-deletion_default   bridge    local

# 查看一下自己创建的网络配置信息
[root@localhost ~]# docker network inspect 3fa16a661c63
[
    {
        "Name": "mynet",
        "Id": "3fa16a661c63da775336a98aadba1447d69e01009f5afbf2e38f2bbb0cdf669d",
        "Created": "2022-01-10T08:18:36.27124654-05:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/24",   # 子网
                    "Gateway": "192.168.0.1"     # 网关
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

启动一个容器,网络配置是我们自己创建的网络

# 启动两个容器,网络配置mynet
[root@localhost ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat
5a85dd02380c7c62714c3fe64e959ad3f1d98d33e44d61e212c3e864e229f927
[root@localhost ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat
a207c17e91dbde264af88b999cd12497d8a649692d5c96d081c8bd09547bb04b

# 查看一下自己创建的网络配置信息,发现两个容器的网络配置都已配置好
[root@localhost ~]# docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "3fa16a661c63da775336a98aadba1447d69e01009f5afbf2e38f2bbb0cdf669d",
        "Created": "2022-01-10T08:18:36.27124654-05:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/24",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "5a85dd02380c7c62714c3fe64e959ad3f1d98d33e44d61e212c3e864e229f927": {
                "Name": "tomcat-net-01",
                "EndpointID": "3efde84d7d3d212a6d4a464467a7baf08a4577036b9c29c116f4a6977451190c",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/24",     # 容器 01 网络配置
                "IPv6Address": ""
				},
            "a207c17e91dbde264af88b999cd12497d8a649692d5c96d081c8bd09547bb04b": {
                "Name": "tomcat-net-02",
                "EndpointID": "1d055768a18f5d2f21b14a90a8182f103cd5d33234918b9acfcca87204545825",
                "MacAddress": "02:42:c0:a8:00:03",
                "IPv4Address": "192.168.0.3/24",  # 容器 02 网络配置
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]


# 再次测试ping连接
[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.100 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.072 ms
64 bytes from 192.168.0.3: icmp_seq=3 ttl=64 time=0.088 ms

# 现在不使用--link,也可以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.117 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.069 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.136 ms

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

好处:

Redis – 不同的集群使用不同的网络,保证集群都是安全和健康的 例如:192.168.0.1/24

MySQL-- 不同的集群使用不同的网络,保证集群是安全和健康的 例如:192.168.0.2/24

网络连通


# 查看docker network 帮助文件
[root@localhost ~]# docker network --help

Usage:  docker network COMMAND

Manage networks

Commands:
  connect     Connect a container to a network   # 连通一个容器到一个网络,结合下图 容器tomcat-01到mynet网络
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
  ls          List networks
  prune       Remove all unused networks
  rm          Remove one or more networks

Run 'docker network COMMAND --help' for more information on a command.

# 测试tomcat-01容器连通mynet网络
# 执行docker network inspect mynet,发现容器tomcat-01加在了mynet网络
[root@localhost ~]# docker network connect mynet tomcat-01
# 再次检测一下mynet配置信息,结果如图:
# 发现tomcat-01容器有两个IP地址{172.17.0.2/16  192.168.0.4/24},类似于阿里云服务:公网ip 私网ip
[root@localhost ~]# docker network inpsect mynet

# 测试tomcat-01 ping tomcat-net-01, 测试成功ok
[root@localhost ~]# docker exec -it tomcat-01 ping tomcat-net-01
# tomcat-02 依然ping不通,但是加入mynet就可以
[root@localhost ~]# docker network connect mynet tomcat-02

结论

如果跨网段连接,需要使用docker network connect命令连通!✌️

实战:部署Redis集群

m : master s : slave

首先移除所有容器

[root@localhost ~]# docker rm -f $(docker ps -aq)
shell 脚本
# 创建网卡
docker network create redis --subnet 172.38.0.0/16
# 创建完之后可以查看一下,[root@localhost ~]# docker network ls
# 查看redis配置 [root@localhost ~]# docker network inspect redis

# 通过脚本创建六个redis配置
# for 循环6次,因为创建六个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

# 接下来启动容器
# 可以用这个做脚本,Python编程,批量运行容器
[root@localhost ~]# docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; \

# 以下的容器启动过程可以用python编个脚本执行,很简单
[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.conf

[root@localhost ~]# 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

[root@localhost ~]# 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

[root@localhost ~]# 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

[root@localhost ~]# docker run -p 6375:6379 -p 16375:16379 --name redis5 \
-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

[root@localhost ~]# 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

# 创建集群
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

# 创建集群代码及运行过程
/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: 43362f7068a0318c81705e6b1d4ed9fe8235e3ec 172.38.0.11:6379
   slots:[0-5460] (5461 slots) master
M: 3062e9bbc8f3b4af1e9b4be85a5cfe42deb86543 172.38.0.12:6379
   slots:[5461-10922] (5462 slots) master
M: ab3fd407c91b53077117f2d4e81a3c52c2082d99 172.38.0.13:6379
   slots:[10923-16383] (5461 slots) master
S: b7ad902f534c30879eaeb27afb7b364c114369b4 172.38.0.14:6379
   replicates ab3fd407c91b53077117f2d4e81a3c52c2082d99
S: 46852447ade8944c1b565dad320b974d70fd9b43 172.38.0.15:6379
   replicates 43362f7068a0318c81705e6b1d4ed9fe8235e3ec
S: 7b2915b456a5d3663df65d878721fcb5659a91ba 172.38.0.16:6379
   replicates 3062e9bbc8f3b4af1e9b4be85a5cfe42deb86543
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: 43362f7068a0318c81705e6b1d4ed9fe8235e3ec 172.38.0.11:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
M: ab3fd407c91b53077117f2d4e81a3c52c2082d99 172.38.0.13:6379
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: 46852447ade8944c1b565dad320b974d70fd9b43 172.38.0.15:6379
   slots: (0 slots) slave
   replicates 43362f7068a0318c81705e6b1d4ed9fe8235e3ec
M: 3062e9bbc8f3b4af1e9b4be85a5cfe42deb86543 172.38.0.12:6379
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: b7ad902f534c30879eaeb27afb7b364c114369b4 172.38.0.14:6379
   slots: (0 slots) slave
   replicates ab3fd407c91b53077117f2d4e81a3c52c2082d99
S: 7b2915b456a5d3663df65d878721fcb5659a91ba 172.38.0.16:6379
   slots: (0 slots) slave
replicates 3062e9bbc8f3b4af1e9b4be85a5cfe42deb86543
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
/data #
进入相应的文件夹,打开配置文件reids.conf,效果如下:

docker 搭建redis集群完成

请注意: master 172.38.0.13 fail , 172.38.0.14 slave 自动变为master

总结:因此有了docker容器技术之后,我们可以利用docker让所有的技术变得简单高效!

IDEA 整合Docker

SpringBoot微服务打包Docker镜像


1、构建SpringBoot项目
# 下图是在centos7系统下的IDEA开发环境
1、打开IDEA
[root@localhost ~]# cd /opt/idea-IU_181.5540.23/bin/
[root@localhost bin]# ./idea.sh

# 进入IDEA环境之后,新建project,本实例均采取默认命名
# 建立一个controller package,再写一个HelloController.java小程序
# 编译成功

# 本地测试一下,浏览器地址栏输入localhost:8080/hello, 成功!

2、打包应用
# 接下来在Maven Projects窗口执行package进行打包,生成jar包

3、编写Dockerfile文件
# 进入File-->Settings-->--Plugins-->docker-->search in repository,安装Docker插件
# 在target文件夹下右键-->File-->新建Dockerfile文件,用于生成docker镜像

4、生成镜像
# 建一个名为idea文件夹,将Dockerfile,demo-0.0.1-SNAPSHOT.jar包文件拷贝过来
[root@localhost ~]# docker build -t bruce_liu .
# 启动容器
[root@localhost ~]# docker run -d -P --name Bruce_liu-springboot-web bruce_liu
5、运行测试、发布
# 在宿主机或者外部电脑浏览器输入http://172.16.12.154:49153/hello,👌

总结:以后我们使用Docker之后,完成项目,交付一个镜像即可!

这是本人学习Docker的一些收获,整理成笔记。希望本人的学习笔记对您有所帮助!如有不正确的地方,欢迎批评指正。

7b2915b456a5d3663df65d878721fcb5659a91ba 172.38.0.16:6379
replicates 3062e9bbc8f3b4af1e9b4be85a5cfe42deb86543
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: 43362f7068a0318c81705e6b1d4ed9fe8235e3ec 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: ab3fd407c91b53077117f2d4e81a3c52c2082d99 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 46852447ade8944c1b565dad320b974d70fd9b43 172.38.0.15:6379
slots: (0 slots) slave
replicates 43362f7068a0318c81705e6b1d4ed9fe8235e3ec
M: 3062e9bbc8f3b4af1e9b4be85a5cfe42deb86543 172.38.0.12:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: b7ad902f534c30879eaeb27afb7b364c114369b4 172.38.0.14:6379
slots: (0 slots) slave
replicates ab3fd407c91b53077117f2d4e81a3c52c2082d99
S: 7b2915b456a5d3663df65d878721fcb5659a91ba 172.38.0.16:6379
slots: (0 slots) slave
replicates 3062e9bbc8f3b4af1e9b4be85a5cfe42deb86543
[OK] All nodes agree about slots configuration.

Check for open slots…
Check slots coverage…
[OK] All 16384 slots covered.
/data #


##### 进入相应的文件夹,打开配置文件reids.conf,效果如下:

[外链图片转存中...(img-qVbynkb0-1641913771944)]

##### docker 搭建redis集群完成 

请注意: master 172.38.0.13 fail , 172.38.0.14 slave 自动变为master

[外链图片转存中...(img-JmyNFu1B-1641913771945)]

总结:因此有了docker容器技术之后,我们可以利用docker让所有的技术变得简单高效!



## SpringBoot微服务打包Docker镜像

----

#### 1、构建SpringBoot项目

```shell
# 下图是在centos7系统下的IDEA开发环境
1、打开IDEA
[root@localhost ~]# cd /opt/idea-IU_181.5540.23/bin/
[root@localhost bin]# ./idea.sh

[外链图片转存中…(img-KjSUuOF1-1641913771946)]

# 进入IDEA环境之后,新建project,本实例均采取默认命名
# 建立一个controller package,再写一个HelloController.java小程序
# 编译成功

[外链图片转存中…(img-OU7uhVQv-1641913771947)]

# 本地测试一下,浏览器地址栏输入localhost:8080/hello, 成功!

[外链图片转存中…(img-Ti1S2xML-1641913771948)]

2、打包应用
# 接下来在Maven Projects窗口执行package进行打包,生成jar包

[外链图片转存中…(img-4Qwxksf3-1641913771949)]

3、编写Dockerfile文件
# 进入File-->Settings-->--Plugins-->docker-->search in repository,安装Docker插件
# 在target文件夹下右键-->File-->新建Dockerfile文件,用于生成docker镜像

[外链图片转存中…(img-BjVWHHLv-1641913771950)]

4、生成镜像
# 建一个名为idea文件夹,将Dockerfile,demo-0.0.1-SNAPSHOT.jar包文件拷贝过来
[root@localhost ~]# docker build -t bruce_liu .
# 启动容器
[root@localhost ~]# docker run -d -P --name Bruce_liu-springboot-web bruce_liu
5、运行测试、发布
# 在宿主机或者外部电脑浏览器输入http://172.16.12.154:49153/hello,👌

[外链图片转存中…(img-TTFA3gWB-1641913771951)]

总结:以后我们使用Docker之后,完成项目,交付一个镜像即可!

这是本人学习Docker的一些收获,整理成笔记。希望本人的学习笔记对您有所帮助!如有不正确的地方,欢迎批评指正。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐