# docker-studys **Repository Path**: jiajia98/docker-studys ## Basic Information - **Project Name**: docker-studys - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-01-27 - **Last Updated**: 2021-07-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Docker ## Docker概述 ### docker为什么会出现? 环境配置是十分麻烦的,每一个机器都要部署环境(集群redis,ES,Hadoop),费时费力 发布一个项目(Redis MySql jdk ES),项目能不能带上环境安装打包 之前在服务配置应用的环境 ,配置超麻烦了,不能够跨平台 Windows,最后发布到Linux java --- apk --- 发布(应用商店)--- 张三使用apk --- 安装即可 java --- jar(环境)--- 打包项目带上环境(镜像)--- (Docker仓库,商店)--- 下载我们发布的镜像 --- 直接运行即可 Docker给以上的问题提出了解决方案 Docker的思想来自于集装箱! Docker通过隔离机制,将服务器利用到极致 ### Docker的历史 2010,几个搞IT的年轻人,在美国成立了一家公司 dotCloud 做一些 pass的云计算服务, LXC 有关容器技术 他们将自己的容器话技术,命名为Docker Docker 刚刚诞生的时候,没有引起行业的注意,就开不下去了,就开源了 开方源代码 2013年Docker开源后,越来越多的人发现了Docker的优点 就火了 2014年4月 Docker1.0发布了 Docker为什么这么火?十分轻巧 在容器 技术出来之前,我们用的都是虚拟机技术 虚拟机:在window中装一个VMware软件,通过这个软件我们可以虚拟出来一台或者多态电脑。笨重!属于虚拟化技术 容器:Docker容器技术也是一种虚拟化技术! Docker是基于Go语言开发的!开源项目, 官网:https://www.docker.com/ 文档:https://docs.docker.com/ 安装:https://docs.docker.com/engine/install/centos/ ### Docker能干嘛 > 之前的虚拟机技术 缺点: 1. 资源占用十分多 2. 冗余步骤多 3. 多个启动很慢 > 容器话技术 容器话技术不是模拟的一个完整的操作系统 比较Docker和 传统虚拟机技术的不同 * 传统虚拟机,虚拟出一条硬件,运行一个完整的操作系统,在这个系统上安装和运行软件 * 容器的应用直接运行在宿主机的内核,容器没有自己的内核的,也没有虚拟硬件,所以就轻便了 * 每个容器互相隔离,都有自己的文件系统,互不影响 > DevOps 开发和运维 **应用更快速的交付和安装部署** Docker 打包发布测试,一键运行 更便捷的升级和扩缩容 使用了Docker之后,我们部署和应用就和搭积木一样 更简单的系统运维 在容器话之后,开发和测试高度一致了 更高效的计算资源利用 Docker是内核级别的虚拟化,可以在一个物理机上运行很多容器实例,服务器被压榨到极致 ## Docker的安装 > 环境准备 1. 会linux 2. Centos7 3. 使用Xshell操作服务器 > 环境查看 ```bash [root@VM-0-2-centos /]# uname -r # 系统内核 3.10.0-1127.19.1.el7.x86_64 ``` ```bash # 系统版本 [root@VM-0-2-centos /]# 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 卸载就的版本 ```bash yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine ``` 2 安装 安装包 ```bash yum install -y yum-utils yum makecache fast ``` 3 设置镜像的仓库 ```bash # 国外的 yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo # 阿里云 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo ``` 4 安装docker相关的内容 ```bash #docker-ce 社区版 ee就是企业版 yum install docker-ce docker-ce-cli containerd.io ``` 5 启动docker ```bash systemctl start docker ``` 6 查看版本 ``` docker version ``` 7 hello-world ```bash docker run hello-world ``` 8 查看镜像 ```bash [root@VM-0-2-centos /]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest bf756fb1ae65 12 months ago 13.3kB ``` 卸载 dokcer ```bash # 卸载依赖 yum remove docker-ce docker-ce-cli containerd.io # 删除目录 rm -rf /var/lib/docker # /var/lib/docker docker的默认工作路径 ``` **阿里云镜像加速** ``` sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://fy4npn6i.mirror.aliyuncs.com"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker ``` ## Docker的基本组成 客户端 * docker build * docker pull * docker run **镜像(image):** docker镜像就好比是一个模板,可以通过这个目标来创建容器服务器 tomcat镜像===run===tomcat容器(提供服务),通过镜像可以创建多个容器 最终就是运行在容器中 **容器(container):** Docker利用容器技术,独立运行一个或者一组应用,通过镜像来创建的 启动,停止,删除 可以理解为一个简易的linux系统 **仓库(repository):** 仓库就是存放镜像的地方 仓库分为公有和私有仓库 Docker Hub 阿里云 华为云 .... ## Docker底层原理 **Docker是怎么工作的?** Docker是一个 CS结构的系统,Docker的守护进程运行在主机上。通过Socket从客户端访问. DockerServer 接受到 DockerClient的指令,就会执行这个命令! **Docker为什么比虚拟机快?** 1. Docker比虚拟机有更少的抽象层 2. Docker利用的宿主机的内核,虚拟机需要的是Guest OS 所以说,新建一个容器的时候,docker不需要虚拟机一样重新加载一个操作系统内核,避免引导,虚拟机试加载Guest OS,分钟级别的,而docker是利用宿主机的操作系统,省略了这个复杂过程 秒级别。 ## Docker的常用命令 ### 帮助命令 ```bash docker version docker info docker 命令 --help ``` 帮助文旦的地址:https://docs.docker.com/engine/reference ### 镜像命令 docker images 查看所有的镜像 ```bash [root@VM-0-2-centos /]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest bf756fb1ae65 12 months ago 13.3kB REPOSITORY # 镜像的仓库 TAG # 版本 IMAGE ID #镜像的id CREATED #镜像的创建时间 SIZE #镜像的大小 -a, --all #列出所有的镜像 -q, --quiet #只显示镜像的id ``` **docker search 搜索镜像** ```bash [root@VM-0-2-centos /]# docker search mysql NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-source relation… 10418 [OK] mariadb MariaDB is a community-developed fork of MyS… 3866 [OK] mysql/mysql-server Optimized MySQL Server Docker images. Create… 763 [OK] # 可选项 --filter=STARS=3000 # 搜索出来镜像是stars大于3000的 ``` docker pull下载镜像 ```bash [root@VM-0-2-centos /]# docker pull mysql Using default tag: latest # 不写版本 默认下载最新的镜像 latest: Pulling from library/mysql a076a628af6f: Pull complete # 分层下载 docker image的核心 联合文件系统 f6c208f3f991: Pull complete 88a9455a9165: Pull complete 406c9b8427c6: Pull complete 7c88599c0b25: Pull complete 25b5c6debdaf: Pull complete 43a5816f1617: Pull complete 1a8c919e89bf: Pull complete 9f3cf4bd1a07: Pull complete 80539cea118d: Pull complete 201b3cad54ce: Pull complete 944ba37e1c06: Pull complete Digest: sha256:feada149cb8ff54eade1336da7c1d080c4a1c7ed82b5e320efb5beebed85ae8c # 签名 Status: Downloaded newer image for mysql:latest docker.io/library/mysql:latest #真实地址 #等价的 docker pull mysql docker pull docker.io/library/mysql:latest # 指定版本下载 [root@VM-0-2-centos /]# docker pull mysql:5.7 5.7: Pulling from library/mysql a076a628af6f: Already exists f6c208f3f991: Already exists 88a9455a9165: Already exists 406c9b8427c6: Already exists 7c88599c0b25: Already exists 25b5c6debdaf: Already exists 43a5816f1617: Already exists 1831ac1245f4: Pull complete 37677b8c1f79: Pull complete 27e4ac3b0f6e: Pull complete 7227baa8c445: Pull complete Digest: sha256:b3d1eff023f698cd433695c9506171f0d08a8f92a0c8063c1a4d9db9a55808df Status: Downloaded newer image for mysql:5.7 docker.io/library/mysql:5.7 ``` **docker rmi删除镜像** ```bash docker rmi -f a70d36bc331a # 根据镜像id删除容器镜像 docker rmi -f $(docker images -aq) # 删除全部容器镜像命令 ``` ### 容器命令 **说明 有了镜像才可以创建容器** **新建容器并启动** ```bash docker run [可选参数] image # 参数的说明 --name="Name" 容器名字 tomcat01 tomcat02 区分容器 -d 后台方式运行 -it 使用交互方式运行,进入容查看内容 -p 指定容器的端口 -p8080:8080 -p ip:主机端口:容器端口 -p 主机端口:容器端口(常用) -p 容器端口 容器端口 -P 大写P随机指定端口 [root@VM-0-2-centos /]# docker run -it centos /bin/bash #启动并进入容器 [root@868d6f46ac9d /]# ls #内部centos的很多命令是不完善的 bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var exit退出容器 回到主机 ``` **列出运行的容器** ```bash docker ps 命令 docker ps 列出当前的 -a 列出当前的+历史的容器 -n=? 显示最近创建的容器 -q 只显示容器的标号 [root@VM-0-2-centos /]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [root@VM-0-2-centos /]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 868d6f46ac9d centos "/bin/bash" 4 minutes ago Exited (0) About a minute ago loving_black 5b898d4ff12c bf756fb1ae65 "/hello" About an hour ago Exited (0) About an hour ago infallible_cerf ``` **退出容器** ``` exit # 直接停止容器并退出 Ctrl + P + Q #容器不停止退出 ``` **删除容器** ```bash docker rm 容器id #删除指定的容器 不能删除正在运行的容器 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 #强制杀掉停止当前容器 ``` ### 常用的其他命令 **后台启动容器** ```bash [root@VM-0-2-centos /]# docker run -d centos b06cae3b22430c565801d97a8bdc5cebdaceac2d6f0fbf990dc6e95abad7bafe #问题 docker ps 发现停止了 # 常见的问题 docker 容器使用后台运行,就必须要有一个前台进程,docker没有发现有应用就会自动停止 # nginx 容器启动后发现自己没有提供服务,就会立刻停止,就是没有服务器了 ``` **查看日志** ```bash docker logs -f -t --tail 容器 没有日志 # 自己编写一段shell脚本 docker run -d centos /bin/sh -c "while true;do echo kuangshen;sleep 1;done" # 显示日志 docker logs -tf --tail 10 075b8381bc5d --tf # 显示日志 --tail 10 # 显示日志条数 ``` **查看容器中的进程信息** ```bash [root@VM-0-2-centos /]# docker top 075b8381bc5d UID PID PPID C STIME TTY TIME CMD root 1726 1706 0 22:19 ? 00:00:00 /bin/sh -c while true;do echo kuangshen;sleep 1;done root 2945 1726 0 22:25 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1 ``` **查看容器的源数据** ```bash docker inspect 075b8381bc5d [ { "Id": "075b8381bc5d98377f524d27b31d19cef3abffb481d67f79aad1064eabbd343a", "Created": "2021-01-26T14:19:58.914585991Z", "Path": "/bin/sh", "Args": [ "-c", "while true;do echo kuangshen;sleep 1;done" ], "State": { "Status": "running", "Running": true, "Paused": false, "Restarting": false, "OOMKilled": false, "Dead": false, "Pid": 1726, "ExitCode": 0, "Error": "", "StartedAt": "2021-01-26T14:19:59.259454986Z", "FinishedAt": "0001-01-01T00:00:00Z" }, "Image": "sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55", "ResolvConfPath": "/var/lib/docker/containers/075b8381bc5d98377f524d27b31d19cef3abffb481d67f79aad1064eabbd343a/resolv.conf", "HostnamePath": "/var/lib/docker/containers/075b8381bc5d98377f524d27b31d19cef3abffb481d67f79aad1064eabbd343a/hostname", "HostsPath": "/var/lib/docker/containers/075b8381bc5d98377f524d27b31d19cef3abffb481d67f79aad1064eabbd343a/hosts", "LogPath": "/var/lib/docker/containers/075b8381bc5d98377f524d27b31d19cef3abffb481d67f79aad1064eabbd343a/075b8381bc5d98377f524d27b31d19cef3abffb481d67f79aad1064eabbd343a-json.log", "Name": "/brave_tharp", "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": [ 0, 0 ], "Isolation": "", "CpuShares": 0, "Memory": 0, "NanoCpus": 0, "CgroupParent": "", "BlkioWeight": 0, "BlkioWeightDevice": [], "BlkioDeviceReadBps": null, "BlkioDeviceWriteBps": null, "BlkioDeviceReadIOps": null, "BlkioDeviceWriteIOps": null, "CpuPeriod": 0, "CpuQuota": 0, "CpuRealtimePeriod": 0, "CpuRealtimeRuntime": 0, "CpusetCpus": "", "CpusetMems": "", "Devices": [], "DeviceCgroupRules": null, "DeviceRequests": null, "KernelMemory": 0, "KernelMemoryTCP": 0, "MemoryReservation": 0, "MemorySwap": 0, "MemorySwappiness": null, "OomKillDisable": false, "PidsLimit": null, "Ulimits": null, "CpuCount": 0, "CpuPercent": 0, "IOMaximumIOps": 0, "IOMaximumBandwidth": 0, "MaskedPaths": [ "/proc/asound", "/proc/acpi", "/proc/kcore", "/proc/keys", "/proc/latency_stats", "/proc/timer_list", "/proc/timer_stats", "/proc/sched_debug", "/proc/scsi", "/sys/firmware" ], "ReadonlyPaths": [ "/proc/bus", "/proc/fs", "/proc/irq", "/proc/sys", "/proc/sysrq-trigger" ] }, "GraphDriver": { "Data": { "LowerDir": "/var/lib/docker/overlay2/05ed30649e5863b96b37d0397c8cf21edeb94a6b2b743e448dd13dd9f6b0ff18-init/diff:/var/lib/docker/overlay2/9776edf6255f5337e4d998c8d8b63ea2a035d2ba69ac90f29507ab73aa9caf11/diff", "MergedDir": "/var/lib/docker/overlay2/05ed30649e5863b96b37d0397c8cf21edeb94a6b2b743e448dd13dd9f6b0ff18/merged", "UpperDir": "/var/lib/docker/overlay2/05ed30649e5863b96b37d0397c8cf21edeb94a6b2b743e448dd13dd9f6b0ff18/diff", "WorkDir": "/var/lib/docker/overlay2/05ed30649e5863b96b37d0397c8cf21edeb94a6b2b743e448dd13dd9f6b0ff18/work" }, "Name": "overlay2" }, "Mounts": [], "Config": { "Hostname": "075b8381bc5d", "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 kuangshen;sleep 1;done" ], "Image": "centos", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": { "org.label-schema.build-date": "20201204", "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": "a9b3192b98237f9290ccc22f38d914283e7ecb4c3821a9f97a85f1aeec6de919", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": {}, "SandboxKey": "/var/run/docker/netns/a9b3192b9823", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "00f5008735fb728d4e8baacf2e09ae186930f55a49d73e9c3cf63445c282cec0", "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": "1fbe32643f7851919b15427ff6686b4979c06ba3677e90d2f66a59105fc9fa4e", "EndpointID": "00f5008735fb728d4e8baacf2e09ae186930f55a49d73e9c3cf63445c282cec0", "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 } } } } ] ``` **进入当前正在运行的容器** ```bash # 我们通常容器都是普通后台方式运行的,需要进入容器,修改一些配置 # 命令 docker exec -it 容器id bashshell docker exec -it 容器id /bin/bash # 测试 ps -ef # 方式二 docker attach 容器id docker attach 容器id 正在执行的当前代码... # docker exec 进入容器后开启一个新的终端,可以在里操作 # docker attach 进入容器正在执行的终端,不会启动新的进程 ``` **从容器内拷贝文件到主机上** ```bash docker cp 容器id:容器内路径 目标的主机路径 docker attach 容器id 进入容器 创建一个/home/test.java 退出 docker cp 85965d3549a0:/home/test.java /home 这样容器外 我们的服务器的home就有了这个test.java # 拷贝是一个手动的过程,未来我们会使用-v 卷的技术,可以实现自动同步 ``` ## 安装练习 ### Docker安装mysql ```bash # 1 拉取镜像 sudo docker pull mysql:5.7 # 2安装 --name指定容器名字 -v目录挂载 -p指定端口映射 -e设置mysql参数 -d后台运行 sudo docker run -p 3306:3306 --name mysql \ -v /mydata/mysql/log:/var/log/mysql \ -v /mydata/mysql/data:/var/lib/mysql \ -v /mydata/mysql/conf:/etc/mysql \ -e MYSQL_ROOT_PASSWORD=leijia31267 \ -d mysql:5.7 # 3 因为有目录映射,所以我们可以直接在镜像外执行 vim /mydata/mysql/conf/my.conf # 复制粘贴 [client] default-character-set=utf8 [mysql] default-character-set=utf8 [mysqld] init_connect='SET collation_connection = utf8_unicode_ci' init_connect='SET NAMES utf8' character-set-server=utf8 collation-server=utf8_unicode_ci skip-character-set-client-handshake skip-name-resolve # 4 重启 docker restart mysql # 安装mysql 8.0.25 docker run -p 3306:3306 --name mysql \ -v /mydata/mysql/data:/var/lib/mysql \ -v /mydata/mysql/conf:/etc/mysql/conf.d \ -e MYSQL_ROOT_PASSWORD=leijia31267 \ -d mysql:8.0.25 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci ``` ### Docker安装Redis ```bash # 创建目录 mkdir -p /mydata/redis/conf touch /mydata/redis/conf/redis.conf # 拉取镜像 docker pull redis # 安装 docker run -p 6379:6379 --name redis \ -v /mydata/redis/data:/data \ -v /mydata/redis/conf/redis.conf:/etc/redis/redis.conf \ -d redis redis-server /etc/redis/redis.conf --requirepass "leijia31267" # 配置关闭redis也持久化 vim /mydata/redis/conf/redis.conf # 插入下面内容 appendonly yes 保存 # 重启 docker restart redis ``` ### Docker 安装 Nginx ```bash docker pull nginx:1.10 # 随便启动一个nginx实例,只是为了复制出配置 docker run -p 80:80 --name nginx -d nginx:1.10 cd /mydata/nginx docker container cp nginx:/etc/nginx . 然后在外部 /mydata/nginx/nginx 有了一堆文件 mv /mydata/nginx/nginx /mydata/nginx/conf # 停掉nginx docker stop nginx docker rm nginx # 创建新的nginx docker run -p 80:80 -p 443:443 --name nginx \ -v /mydata/nginx/html:/usr/share/nginx/html \ -v /mydata/nginx/logs:/var/log/nginx \ -v /mydata/nginx/conf:/etc/nginx \ -d nginx:1.10 docker update nginx --restart=always ``` ### Docker安装 nginx 并配置ssl证书实现https ```shell # 1. 运行 docker run --name mynginx \ -p 443:443 \ -p 80:80 \ --privileged=true \ -v /mydata/nginx/html:/usr/share/nginx/html \ -v /mydata/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \ -v /mydata/nginx/conf/conf.d/default.conf:/etc/nginx/conf.d/default.conf \ -v /mydata/nginx/logs:/var/log/nginx \ -v /mydata/nginx/ssl:/ssl \ -d nginx # 2 nginx.conf #运行nginx的用户 user nginx; #启动进程设置成和CPU数量相等 worker_processes 1; #全局错误日志及PID文件的位置 error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; #工作模式及连接数上限 events { #单个后台work进程最大并发数设置为1024 worker_connections 1024; } http { #设定mime类型 include /etc/nginx/mime.types; default_type application/octet-stream; #设定日志格式 log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; #设置连接超时的事件 keepalive_timeout 65; #开启GZIP压缩 #gzip on; include /etc/nginx/conf.d/*.conf; } # 3 default.conf server { listen 80; #侦听80端口,如果强制所有的访问都必须是HTTPs的,这行需要注销掉 server_name hua.yfkdu.cn; #域名 #charset koi8-r; #access_log /var/log/nginx/host.access.log main; # 定义首页索引目录和名称 location / { root /usr/share/nginx/html; index index.html index.htm; } #定义错误提示页面 #error_page 404 /404.html; #重定向错误页面到 /50x.html error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } server { listen 80; #侦听80端口,如果强制所有的访问都必须是HTTPs的,这行需要注销掉 server_name hua.yfkdu.cn; #域名 #charset koi8-r; #access_log /var/log/nginx/host.access.log main; # 定义首页索引目录和名称 location / { root /usr/share/nginx/html; index index.html index.htm; } #定义错误提示页面 #error_page 404 /404.html; #重定向错误页面到 /50x.html error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } server { listen 443; server_name hua.yfkdu.cn; #域名 # 增加ssl ssl on; #如果强制HTTPs访问,这行要打开 ssl_certificate /ssl/scs1623825666175_hua.yfkdu.cn_server.crt; ssl_certificate_key /ssl/scs1623825666175_hua.yfkdu.cn_server.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; # 指定密码为openssl支持的格式 ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # 密码加密方式 ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; # 依赖SSLv3和TLSv1协议的服务器密码将优先于客户端密码 ssl_prefer_server_ciphers on; # 定义首页索引目录和名称 location / { root /usr/share/nginx/html; index index.html index.htm; } #重定向错误页面到 /50x.html error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } ``` ### nginx反向代理1 ``` http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; include /etc/nginx/conf.d/*.conf; server { listen 80; server_name 119.3.255.103; location / { root html; proxy_pass http://192.168.0.44:8081; index index.html index.htm; } } } ``` ### nginx反向代理2 ``` server { listen 80; server_name 119.3.255.103; location / { root /usr/share/nginx/html/dist; index index.html index.htm; } location ~ /api1/ { proxy_pass http://192.168.0.44:8081; } location ~ /api2/ { proxy_pass http://192.168.0.44:8082; } } ``` ```bash # 1搜索镜像 docker search nginx 网站有详细信息Dockerhub # 2下载镜像 docker pull nginx # 3 启动 -d 后台运行 --name 给容器起一个新的名字 -p 暴露端口 服务器端口:容器内部端口 docker run -d --name nginx01 -p 6677:80 nginx # 4 测试 curl localhost:6677 # 5 进入nginx容器 docker exec -it ea9ca6654fc4 /bin/bash # 6 查看配置文件 whereis nginx root@ea9ca6654fc4:/# cd /etc/nginx root@ea9ca6654fc4:/etc/nginx# ls conf.d koi-utf mime.types nginx.conf uwsgi_params fastcgi_params koi-win modules scgi_params win-utf ``` 我们每次改动nginx配置文件,都需要进入容器内部,十分麻烦,我们要是可以在容器外部提供一个映射路径,在容器外部部署项目,容器外部修改文件,容器内部修改文件-v卷的技术 ### Docker 安装 Tomcat ```bash # 官方的使用 用完即删除 docker run -it --rm tomcat:9.0 # 我们之前的启动都是后台 停止了容器之后,容器还是可以查到的 # 下载 启动 docker pull tomcat docker run -d --name tomcat02 -p 6677:8080 tomcat # 测试 [root@VM-0-2-centos home]# docker exec -it tomcat02 /bin/bash root@39fb9ff16495:/usr/local/tomcat# ls BUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps.dist CONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps work root@39fb9ff16495:/usr/local/tomcat# cd webapps root@39fb9ff16495:/usr/local/tomcat/webapps# ls #问题linux命令少了 webapps 没有东西 root@39fb9ff16495:/usr/local/tomcat/webapps# # 只保证最少可用的镜像 ``` ### Docker 部署 ES + kibana ```bash # es暴露的端口很多 # es十分耗内存 # es的数据一般需要放到安全目录 挂载 #官方 --net somenetwork 网络配置 docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2 docker stats 查看服务器运行的的 cpu的状态 #太占内存了 我们要做一个限制,修改配置文件 -e 环境配置修改 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 # 映射安装 docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \ -e "discovery.type=single-node" \ -e ES_JAVA_OPTS="-Xms64m -Xmx512m" \ -v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \ -v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \ -v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \ -d elasticsearch:7.6.2 ``` ### Docker安装RabbitMQ ```bash # 1 查看MQ是否存在 docker search rabbitmq:management # 2 将镜像下载下来 docker pull rabbitmq:management #3 安装docker镜像 docker run -d --name rabbit -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -p 15672:15672 -p 5672:5672 -p 25672:25672 -p 61613:61613 -p 1883:1883 rabbitmq:management # 说明 命令中的【RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin】是web管理平台的用户名和密码 【 -p 15672:15672】 是控制平台docker映射到系统的对应端口 【 -p 5672:5672】 是应用程序的访问端口 ``` ## 可视化 * portainer ```bash 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的图形化界面管理工具 提供一个后台面板让我们使用 ## Docker镜像讲解 ### 镜像是什么 镜像是一种轻量级,可执行的独立软件包,用来打包软件的运行环境和基于环境开发的软件,它包含运行某个软件的所有内容,包括代码,运行时、库、环境变量和配置文件 ### Docker镜像加载原理 **UnioFS 联合文件系统** UnioFS 联合文件系统 :是一种分层,轻量级并且高性能的文件系统,它支持文件系统的修改作为一次提交来一层层叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像()没有父镜像,可以制作各种具体的应用镜像 特性:一次同时加载多个文件系统,单从外面来看,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有的底层的文件和目录 **Docker镜像加载原理** docker的镜像实际上由一层层的文件系统组合,这种层级的文件系统UnionFS bootfs(boot file system)主要包含bootleader和kerrnel,bootloader主要是引导kernel,linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层bootfs,这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核,当boot加载完成之后,整个内核就都在内存中了,此时内存的使用权有bootfs转交给内核,此时系统也会卸载bootfs rootfs 在bootfs之上,包含的就是典型的linux系统中的/dev/proc/bin/etc等标准目录和文件,rootfs就是各种不同的操作系统发行版 Ubuntu,Centos等等 平时我们装的centos都是好几个G为什么Docker却很小 对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层只用用的是Jost的kemel,自己需要提供rootfs就可以了,由此可见多余不同的linux发行按,rootfs会有差别,因此不同的发行版可以公用bootfs ### 分层理解 我们下载的时候,可以看到镜像是一层层的下载 最大的好处,我觉得就是资源共享了,比如有U多个集镜像都是从相同的Base镜像而来,那么宿主机就只需要在磁盘上保留一份base镜像,同时内存中也只需要加载一份base进行,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享 **理解** 所有的Docker镜像都起始于一个基础镜像层,当进行修改或者增加新的内容时,就会在当前的镜像层上创建新的镜像层。 ### commit镜像 ```bash docker commit 提交容器为一个新的副本 docker commit -m="提交的信息" -a="作者" 目标镜像名:[tab] # 启动一个tomcat # 发现webapps 没有东西 # cp -r webapps.dist/* webapps [root@VM-0-2-centos home]# docker commit -a="jialei" -m "add webapps application" cec6b3aba29a tomcatjia:1.1 sha256:9e1bdcbfd62db747a8ea7cfc9b534d0ad1bf483484c03bf3c2c55927c85ca448 [root@VM-0-2-centos home]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE tomcatjia 1.1 9e1bdcbfd62d 33 seconds ago 654MB redis latest 621ceef7494a 13 days ago 104MB tomcat latest 040bdb29ab37 13 days ago 649MB elasticsearch 7.6.2 f29a1ee41030 10 months ago 791MB ``` ## 容器数据卷 容器之间可以有个数据共享的技术Docker容器中产生的数据可以同步到本地!这就是 卷技术 将容器内的目录挂载到虚拟机或者linux服务器上 总结一句话:容器的持久化和同步操作,容器间也是可以数据共享的! ### 使用数据卷 **方式一:使用命令来挂载** ```bash docker run -it -v 主机目录:容器内目录 -p 主机端口:容器端口 "Mounts": [ { "Type": "bind", "Source": "/home/ceshi", # 主机的地址 "Destination": "/home", # docker容器内的地址 "Mode": "", "RW": true, "Propagation": "rprivate" } ], ``` 是个双向绑定的技术,就算容器停止也还是 会同步 这样我们在本地修改在容器内会自动同步 **安装mysql** ```bash docker pull mysql:5.7 #配置 -d 后台运行 -p 端口映射 -v 数据卷挂载 -e 环境配置 --name 别名 docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7 # 启动成功后可以本地连接测试一下 将容器删除后 发现了我们挂载到本地的数据仍然在 这就实现了数据在本地的持久化 ``` **具名和匿名挂载** ```bash #匿名挂载 -v 容器内路径 docker run -d -P --name nginx01 -v /etc/nginx nginx # 查看所有卷的情况 匿名卷的挂载 docker volume ls DRIVER VOLUME NAME local 92b7db819474501db86c9f31635127bb13e3299177c8b5df1f35c8a14ff13bc8 # 这种就是匿名挂载 -v的时候我们只写了容器内的路径,没有写容器外的路径 # 具名挂载 docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx [root@VM-0-2-centos data]# docker volume ls DRIVER VOLUME NAME local 92b7db819474501db86c9f31635127bb13e3299177c8b5df1f35c8a14ff13bc8 local juming-nginx # 通过 -v 卷名:容器内路径 # 查看一下这卷 [root@VM-0-2-centos data]# docker volume inspect juming-nginx [ { "CreatedAt": "2021-01-27T14:17:08+08:00", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data", "Name": "juming-nginx", "Options": null, "Scope": "local" } ] # 所有容器的卷没有指定目录的情况下 都在 /var/lib/docker/volumes/xxxxx/_data ``` 我们通过具名挂载可以方便的找到我们的一个卷,这也是大多数情况下使用的 不建议使用匿名挂载 ```bash # 如何确定是 具名挂载 还是匿名挂载 还是指定目录挂载 -v 容器内路径 匿名挂载 -v 卷名:容器内路径 具名挂载 -v /宿主机路径:容器内路径 指定目录挂载 ``` 拓展 ```bash # 通过 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镜像的构建文件 命令脚本 **方式二** ```bash # 通过这脚本可以生成镜像 镜像是一层一层的,脚本就是一个个的命令,每个命令都是一层 # 1 创建一个文件 dockerfile1 名字可以修改 但是建议用Dockerfile # 指令都是大写的 FROM centos VOLUME ["volume01","volume02"] # 自己的目录数据卷目录 CMD echo "---end---" CMD /bin/bash # 这里的每个命令就是镜像的一层 # 2 docker build -f dockerfile1 -t kuangshen/centos:1.1.0 . 注意不要忘掉 . docker images REPOSITORY TAG IMAGE ID CREATED SIZE kuangshen/centos 1.1.0 fe5d4c1513be 57 seconds ago 209MB ``` 这种方式 我们未来使用的十分多,因为我们通常使用自己的镜像 假设构建的时候没有挂载卷名,需要手动挂载 -v 卷名:容器内路径 **数据卷容器** ```bash # 创建docker01 docker run -it --name docker01 kuangshen/centos:1.1.0 # 创建docker02 docker run -it --name docker02 --volumes-from docker01 kuangshen/centos:1.1.0 # 这样两个容器就关联了 在docker02 中创建的数据 在docker01 也会自动创建关联 --volumes-from 可以实现容器间的数据共享 # 测试 删除docker01 其他容器的数据还存在 ``` 结论 容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器为止 但是一旦你持久化到本地,这个时候,本地的数据是不会删除的 dockerfile 是用来构建docker镜像的文件,命令参数脚本 **构建步骤** 1. 编写一个dockerfile文件 2. docker build 构建称为一个镜像 3. docker run 运行镜像 4. docker push 发布镜像(DockerHub 阿里云镜像仓库) ```bash # 官方的centos Dockerfile FROM scratch ADD centos-7-x86_64-docker.tar.xz / LABEL \ org.label-schema.schema-version="1.0" \ org.label-schema.name="CentOS Base Image" \ org.label-schema.vendor="CentOS" \ org.label-schema.license="GPLv2" \ org.label-schema.build-date="20201113" \ org.opencontainers.image.title="CentOS Base Image" \ org.opencontainers.image.vendor="CentOS" \ org.opencontainers.image.licenses="GPL-2.0-only" \ org.opencontainers.image.created="2020-11-13 00:00:00+00:00" CMD ["/bin/bash"] ``` 很多的基础包,很多功能没有,我们通常会搭建自己的镜像 ### DockerFile的构建 **基础知识** 1. 每个保留关键字(指令) 都必须是大写字母 2. 执行从上到下 3. #表示注释 4. 每一个指令都会创建提交一个新的镜像层,并提交 dockerfile是面向开发的,我们以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单 Docker镜像逐渐成为了企业交付的标准 必须要掌握 Dockerfile 构建文件 定义了一切的步骤,源代码 Dockerimages 通过Dockerfile构建生成的镜像,最终要发布和运行的产品 Docker 容器,就是镜像运行起来的服务 ### Dockerfile的指令 以前我们就是用别人的的 ```bash # FROM 基础镜像 一切从这里构建 # MAINTAINER 镜像是谁写的 姓名+邮箱 # RUN 镜像构建的时候需要运行的命令 # ADD 步骤 tomcat镜像,这个tomcat压缩包 添加内容 # WORKDIR 镜像的工作目录 # VOLUME 挂载的目录 # EXPOSE 暴露端口 # CMD 指定容器启动的时候要运行的命令 只有最后一个会生效,可被替代 # ENTRYPOINT 指定这个容器启动的时候需要运行的命令,可以追加命令 # ONBUILD 当构建一个被继承Dockerfile 这个时候就会运行 ONBUILD 的指令触发指令 # COPY 类似于ADD 将我们的文件拷贝到镜像中 # ENV 构建的时候设置环境变量 ``` **实战测试** FROM scratch # dockerhub中99%都是从他开始的 然后配置其他的软件和配置 创建一个自己的centos ``` 1 编写Dockerfile配置文件 FROM centos MAINTAINER jiajia<980436918@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 通过这个文件构建镜像 docker build -f mydockerfile -t mycentos:0.1 3 测试运行 ``` **对比之前原生的centos** * 之前的工作目录是 / 根目录 现在是/usr/local * 之前 没添加的 网络 和 vim的命令自己的有 查看构建历史 ``` [root@VM-0-2-centos dockerfile]# docker history 2c117a3befb0 IMAGE CREATED CREATED BY SIZE COMMENT 2c117a3befb0 5 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B 09b937babada 5 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B 0d3cfe263ecb 5 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B 88450b84b947 5 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B f91a74626402 5 minutes ago /bin/sh -c yum -y install net-tools 23.3MB 0e426aece45d 5 minutes ago /bin/sh -c yum -y install vim 58.1MB cf25a7ae4df5 5 minutes ago /bin/sh -c #(nop) WORKDIR /usr/local 0B 69cfab8b559a 5 minutes ago /bin/sh -c #(nop) ENV MYPATH=/usr/local 0B bd494691b4b3 5 minutes ago /bin/sh -c #(nop) MAINTAINER jiajia<9804369… 0B 300e315adb2f 7 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B 7 weeks ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B 7 weeks ago /bin/sh -c #(nop) ADD file:bd7a2aed6ede423b7… 209MB ``` **CMD和ENTRYPORT 的区别** ```bash # CMD 指定容器启动的时候要运行的命令 只有最后一个会生效,可被替代 # ENTRYPOINT 指定这个容器启动的时候需要运行的命令,可以追加命令 ``` 测试cmd ```bash 1创建一个dockerfile文件 FROM centos CMD ["ls","-a"] 2运行 docker build -f dockerfile-cmd-test -t cmdtest 3 进入容器 [root@VM-0-2-centos dockerfile]# docker run ab1de7d03689 . .. .dockerenv bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var [root@VM-0-2-centos dockerfile]# # 发现了我们 的 ls -a 生效了 # 执行了一个命令 -l [root@VM-0-2-centos dockerfile]# docker run ab1de7d03689 -l docker: Error response from daemon: OCI runtime create failed: container_linux.go:370: starting container process caused: exec: "-l": executable file not found in $PATH: unknown. # CMD 的情况下 -l 替换了CMD ["ls","-a"],不是命令所以报错 ``` 测试 ENTRYPOINT ``` 1 构建dockerfile文件 FROM centos ENTRYPOINT ["ls","-a"] 2 build镜像 docker build -f dockerfile-cmd-entrypoint -t entrypoint-test . 3 docker run 118f93061ea4 -l total 56 drwxr-xr-x 1 root root 4096 Jan 27 09:04 . drwxr-xr-x 1 root root 4096 Jan 27 09:04 .. -rwxr-xr-x 1 root root 0 Jan 27 09:04 .dockerenv lrwxrwxrwx 1 root root 7 Nov 3 15:22 bin -> usr/bin drwxr-xr-x 5 root root 340 Jan 27 09:04 dev drwxr-xr-x 1 root root 4096 Jan 27 09:04 etc 我们的追加命令 是直接拼接在后面的 ``` Docker中很多的命令都十分的相似,我们需要了解他们的区别 最好是去测试它 **实战 tomcat镜像** 1. 准备镜像文件 tomcat压缩包 jdk的压缩包 2. 编写dockerfile文件 官方命名 Dockerfile build的时候不需要 -f 指定了 ```dockerfile FROM centos MAINTAINER jiajia<980436918@qq.com> COPY readme.txt /usr/local/readme.txt ADD jdk-8u281-linux-x64.tar.gz /usr/local/ ADD apache-tomcat-9.0.41.tar.gz /usr/local/ RUN yum -y install vim ENV MYPATH /usr/local WORKDIR $MYPATH ENV JAVA_HOME /usr/local/jdk1.8.0_281 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.41 ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.41 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin EXPOSE 8080 CMD /usr/local/apache-tomcat-9.0.41/bin/startup.sh && tail -F /url/local/apache-tomcat-9.0.41/bin/logs/catalina.out ``` 3. 构建镜像 ```bash docker build -t dirtomcat . ``` 4. 运行 ``` docker run -d -p 9090:8080 --name jiatomcat2 -v /home/jia/build/tomcat/test:/usr/local/apache-tomcat-9.0.41/webapps/test -v /home/jia/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.41/logs diytomcat ``` 5. 访问镜像 ``` docker exec -it xxxxID /bin/bash ``` 6. 访问测试 7. 发布 ```xml ``` ```jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> hello jiajia Hello World!
<% System.out.println("我的javaweb项目"); %> ``` ## Docker 网络 ### 理解Docker0 ```bash [root@VM-0-2-centos test]# ip addr 1: lo: 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: eth0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 52:54:00:5f:9c:bd brd ff:ff:ff:ff:ff:ff inet 172.21.0.2/20 brd 172.21.15.255 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::5054:ff:fe5f:9cbd/64 scope link valid_lft forever preferred_lft forever 3: docker0: mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:dd:f0:53:55 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:ddff:fef0:5355/64 scope link valid_lft forever preferred_lft forever [root@VM-0-2-centos test]# 1: lo: 本机回环地址 2: eth0: 内网地址 3: docker0: docker0 地址 ``` 三个网络 > docker 是如何处理网络的访问的 ```bash [root@VM-0-2-centos test]# docker run -d -P --name tomcat01 tomcat # 查看容器内部的网络地址 ip addr 会得到eth0@if97 地址 这就是docker给他分配的 [root@VM-0-2-centos test]# docker exec -it tomcat01 ip addr 1: lo: 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 96: eth0@if97: 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同容器内部? # ping 172.17.0.2 # linux可以ping通docker容器内部 ``` **原理** 我们每启动一个docker容器,docker就会给安装的docker容器 分配一个ip,我们只要安装了docker,就会有一个网卡docker0 桥接模式,使用的技术是 evth-pair技术! **再启动一个容器** **发现有多了一对网卡** > 我们发现这个容器带来的网卡,都是一对一对出现的 > > evth-pair 就是一对一对的虚拟设备接口,他们都是成对出现的,一段连着协议,一段彼此相连 > > 正因为有了这个特性 就充当了一个桥梁,连接各种虚拟网络设备 这样 tomcat01 tomcat02 可以互相ping 通 容器之间是可以互相 ping 通的 结论 tomcat01 和 tomcat02 是公用的一个路由器 docker0 255.255.0.1/16 Docker 使用的的是linux的桥接技术,所有的网络接口都是虚拟的,虚拟的转发效率高 只要容器删除对应的 网桥就 没有了 **--link** ```bash [root@VM-0-2-centos /]# docker exec -it tomcat02 ping tomcat01 ping: tomcat01: Name or service not known docker run -d -P --name tomcat03 --link tomcat02 tomcat 92e1497870f0f00cd09a83bef62e1a29d6eb9f571600e88ad6d7513561d828bd [root@VM-0-2-centos /]# docker exec -it tomcat03 ping tomcat02 PING tomcat02 (172.17.0.3) 56(84) bytes of data. 64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.115 ms 64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.060 ms [root@VM-0-2-centos /]# docker exec -it tomcat02 ping tomcat03 ping: tomcat03: Name or service not known 3 可以 ping 通2 2 不可以 ping 通3 ``` 就可以通过服务名来ping通了 但是不建议使用 ### 自定义网络 容器互联 查看所有的网络 ```bash [root@VM-0-2-centos /]# docker network ls NETWORK ID NAME DRIVER SCOPE 1fbe32643f78 bridge bridge local 30caac4544d3 host host local fe0f8e69c050 none null local ``` **网络模式** * bridge 桥接 在docker上搭桥(默认,我们自己创建也使用桥接模式) * none 不配置网络 * host 主机模式 和宿主机公用 * container 容器网络连通 **测试** ```bash # 不写默认为 --net bridge 就是docker0 [root@VM-0-2-centos /]# docker run -d -P --name tomcat01 --net bridge tomcat # docker0 默认域名不能访问 # 我们可以自定义一个网络 mynet --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 [root@VM-0-2-centos /]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet 96c559a511d952ddd173b555c0bf1a5a1ad43d487949bc0515aedfd4a199e195 You have new mail in /var/spool/mail/root [root@VM-0-2-centos /]# docker network ls NETWORK ID NAME DRIVER SCOPE 1fbe32643f78 bridge bridge local 30caac4544d3 host host local 96c559a511d9 mynet bridge local fe0f8e69c050 none null local ``` 查看自己的网络 ```bash docker network inspect mynet [ { "Name": "mynet", "Id": "96c559a511d952ddd173b555c0bf1a5a1ad43d487949bc0515aedfd4a199e195", "Created": "2021-01-27T20:03:23.881693391+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "192.168.0.0/16", "Gateway": "192.168.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": {}, "Options": {}, "Labels": {} } ] ``` 创建容器使用自己的网络 ```bash [root@VM-0-2-centos /]# docker run -d -P --name tomcat-net-01 --net mynet tomcat b1e73b600d8024edcde3dc18a1a457e986b7f87c60191863cf77c09ed2a30725 [root@VM-0-2-centos /]# docker run -d -P --name tomcat-net-02 --net mynet tomcat b6015bfb6d8e9c49240c0e03650eb02f90b423fadc4851588d9559f55decf9d3 # 自己创建的网络可以互相ping通 通过容器名 [root@VM-0-2-centos /]# 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.067 ms 64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.056 ms ``` **连通 docker0 和mynet** ```bash 连通 tomcat01 和mynet 连通之后就是 将tomcat01 放到了mynet 网络下 一个容器两个ip ``` ``` [root@VM-0-2-centos /]# docker network connect mynet tomcat01 [root@VM-0-2-centos /]# docker network inspect mynet [ { "Name": "mynet", "Id": "96c559a511d952ddd173b555c0bf1a5a1ad43d487949bc0515aedfd4a199e195", "Created": "2021-01-27T20:03:23.881693391+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "192.168.0.0/16", "Gateway": "192.168.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "b1e73b600d8024edcde3dc18a1a457e986b7f87c60191863cf77c09ed2a30725": { "Name": "tomcat-net-01", "EndpointID": "1c93ecbc08cefe67aff8c69b1da5521ec9d659755957f57bf41064ce4382f53f", "MacAddress": "02:42:c0:a8:00:02", "IPv4Address": "192.168.0.2/16", "IPv6Address": "" }, "b6015bfb6d8e9c49240c0e03650eb02f90b423fadc4851588d9559f55decf9d3": { "Name": "tomcat-net-02", "EndpointID": "1b8c53588f16e2cb495401f7808cd996dc897913262934db39524df3e32c25b7", "MacAddress": "02:42:c0:a8:00:03", "IPv4Address": "192.168.0.3/16", "IPv6Address": "" }, "e0c8649dbc8a8a55e9183938655f05d52ddea31eb51ec8a2663aaf9b718dbdb3": { "Name": "tomcat01", "EndpointID": "f4d0004ffebff75b8b25c8ea997811b5187880b1854c1cece9b32b7868916e09", "MacAddress": "02:42:c0:a8:00:04", "IPv4Address": "192.168.0.4/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ] ``` 只有连通的容器可以 没有连通的依然不能ping通 ``` [root@VM-0-2-centos /]# docker exec -it tomcat01 ping tomcat-net-01 PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data. 64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.065 ms 64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.074 ms 64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.058 ms ^C --- tomcat-net-01 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 1001ms rtt min/avg/max/mdev = 0.058/0.065/0.074/0.011 ms [root@VM-0-2-centos /]# docker exec -it tomcat02 ping tomcat-net-01 ping: tomcat-net-01: Name or service not known ```