赞
踩
目录
镜像(image):
Docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,tomcat镜像===> run ===>tomcat01 容器 (提供服务器),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)。
容器(container):
Docker利用容器技术,独立运行一个或者一个组应用,通过镜像来创建的。
启动,停止,删除,基本命令!
目前就可以把这个容器理解为就是一个简易的linux系统
仓库(repository):
仓库就是存放镜像的地方!
仓库分为公有仓库和私有仓库!
Docker Hub(默认为国外的)
阿里云...都有容器服务器(配置镜像加速!)
# 1.卸载旧的版本 yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine # 2.安装需要的安装包 yum install -y yum-utils # 3.设置镜像的仓库 yum-config-manager \ --add-repo \ http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 国内阿里云的镜像 十分快捷 # 更新yum软件包索引 yum makecache fast # 4.安装docker docker-ce 社区版 ee 企业版 yum install docker-ce docker-ce-cli containerd.io # 5.启动docker systemctl start docker # 6.使用docker version 是否安装成功
# 7.hello-world docker run hello-world #出现Hello from Docker! 证明你的docker安装成功 仅此而已!
# 8.查看一个下载的这个 hello-world 镜像 [root@docker /]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest feb5d9fea6a5 3 weeks ago 13.3kB ubuntu 16.04 b6f507652425 7 weeks ago 135MB nginx latest dd34e67e3371 2 months ago 133MB
了解:卸载docker
# 1.卸载依赖 yum remove docker-ce docker-ce-cli containerd.io # 2.删除资源 rm -rf /var/lib/docker rm -rf /var/lib/containerd # /var/lib/docker docker的默认工作路径!
1.登录阿里云找到容器服务
2.找到镜像加速地址
配置使用
sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://z4lqcsrm.mirror.aliyuncs.com"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker
Docker是怎么工作的?
Docker是一个 Client - Server 结构的系统,Docker的守护进程运行在主机上。通过Socket从客户端访问!
DockerServer 接收到 Docker-Client 的指令,就会执行这个命令!
Docker为什么比VM快?
1.Docker有着比虚拟机更少的抽象层。
2.Docker利用的是宿主机的内核,vm需要的是Guest OS。
所以说,新建一个容器的时候,docker不需要像虚拟机一样重新加载一个操作系统内核,避免引导,虚拟机是加载 Guest OS,虚拟机加载是分钟级别的,而Docker是利用宿主机的操作系统,省略了这个复杂的过程,加载是秒级别的!
docker version # 显示docker的版本信息 docker info # 显示docker的系统信息,包括镜像和容器的数量 docker 命令 --help # 帮助命令
帮助文档的地址:docker build | Docker Documentation
[root@docker ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest feb5d9fea6a5 3 weeks ago 13.3kB # 解释 REPOSITORY 镜像的仓库源 TAG 镜像的标签 IMAGE ID 镜像的ID CREATED 镜像的创建时间 SIZE 镜像的大小 # 可选项 -a, --all # 列出所有镜像 -q, --quiet # 只显示镜像的ID
docker search 搜索镜像
[root@docker ~]# docker search mysql NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-source relation… 11556 [OK] mariadb MariaDB Server is a high performing open sou… 4398 [OK] # 可选项,通过搜藏来过滤 --filter=stars=3000 # 搜索出来的镜像就是stars大于3000的 [root@docker ~]# docker search mysql --filter=stars=3000 NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-source relation… 11556 [OK] mariadb MariaDB Server is a high performing open sou… 4398 [OK] [root@docker ~]# docker search mysql --filter=stars=5000 NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-source relation… 11556 [OK]
docker pull 下载镜像
# 下载镜像 docker pull 镜像名[:tag] [root@docker ~]# docker pull mysql Using default tag: latest # 如果不写 tag,默认就是 latest latest: Pulling from library/mysql b380bbd43752: Pull complete # 分层下载,docker iamge的核心,联合文件系统 f23cbf2ecc5d: Pull complete 30cfc6c29c0a: Pull complete b38609286cbe: Pull complete 8211d9e66cd6: Pull complete 2313f9eeca4a: Pull complete 7eb487d00da0: Pull complete 4d7421c8152e: Pull complete 77f3d8811a28: Pull complete cce755338cba: Pull complete 69b753046b9f: Pull complete b2e64b0ab53c: Pull complete Digest: sha256:6d7d4524463fe6e2b893ffc2b89543c81dec7ef82fb2020a1b27606666464d87 # 签名,防伪标志 Status: Downloaded newer image for mysql:latest docker.io/library/mysql:latest # 真实地址 # 等价于它 docker pull mysql docker pull mysql docker.io/library/mysql:latest # 指定版本下载 docker pull mysql:版本号 #版本号必须官网hub.docker.com库里面有才可以 [root@docker ~]# docker pull mysql:5.7 5.7: Pulling from library/mysql b380bbd43752: Already exists f23cbf2ecc5d: Already exists 30cfc6c29c0a: Already exists b38609286cbe: Already exists 8211d9e66cd6: Already exists 2313f9eeca4a: Already exists 7eb487d00da0: Already exists a71aacf913e7: Pull complete 393153c555df: Pull complete 06628e2290d7: Pull complete ff2ab8dac9ac: Pull complete Digest: sha256:2db8bfd2656b51ded5d938abcded8d32ec6181a9eae8dfc7ddf87a656ef97e97 Status: Downloaded newer image for mysql:5.7 docker.io/library/mysql:5.7
docker rmi 删除镜像!
[root@docker ~]# docker rmi -f 镜像ID # 删除指定的镜像 [root@docker ~]# docker rmi -f 镜像ID 镜像ID 镜像ID # 删除多个镜像 [root@docker ~]# docker rmi -f $(docker images -aq) # 删除全部的镜像
说明:我们有了镜像才可以创建容器,linux,下载一个centos镜像来测试学习
docker pull centos
新建容器并启动
docker run [可选参数] image # 参数说明 --name="Name" 容器名字 tomcat01 tomcat02,用来区分容器 -d 后台方式运行 -it 使用交互方式运行,进入容器查看内容 -P 指定容器的端口 -p 8080:8080 -p ip:主机端口:容器端口 -p 主机端口:容器端口(常用) -p 容器端口 容器端口 -p 随机指定端口 # 测试,启动并进入容器 [root@docker ~]# docker run -it centos /bin/bash [root@3237e6fbe6d5 /]# ls #查看容器内的centos,基础版本,最多命令都是不完善的! bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var # 从容器中退回主机 [root@3237e6fbe6d5 /]# exit exit [root@docker /]# ls bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
列出所有的运行的容器
# docker ps 命令 #列出当前正在运行的容器 -a #列出当前正在运行的容器+顺带带出历史运行过的容器 -n=?(参数) # 显示最近创建的容器 -q # 只显示容器的编号 [root@docker /]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [root@docker /]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3237e6fbe6d5 centos "/bin/bash" 25 minutes ago Exited (0) 5 minutes ago condescending_benz 3a4659754565 hello-world "/hello" 18 hours ago Exited (0) 18 hours ago quirky_lumiere d3f61b12b57d hello-world "/hello" 19 hours ago Exited (0) 19 hours ago hopeful_taussig 80085d9ac954 hello-world "/hello" 19 hours ago Exited (0) 19 hours ago affectionate_bardeen e0853f1d7892 nginx "/docker-entrypoint.…" 7 weeks ago Exited (255) 9 days ago 0.0.0.0:80->80/tcp, :::80->80/tcp webserver 50de615abbc5 ubuntu:16.04 "/bin/bash" 7 weeks ago Exited (255) 9 days ago jovial_visvesvaraya d9f85898935b ubuntu:16.04 "/bin/sh -c 'while t…" 7 weeks ago Exited (255) 9 days ago kind_zhukovsky [root@docker /]#
推出容器
exit # 直接容器停止并退出 Ctrl + p + Q # 容器不停止退出
删除容器
docker rm 容器id # 删除指定的容器,不能删除正在运行的容器,如果要强制删除要rm -f docker rm -f $(docker ps -aq) # 删除所有的容器 docker ps -a -q|xargs docker rm #删除所有的容器
启动和停止容器的操作
docker start 容器id # 启动容器 docker restart 容器id # 重启容器 docker stop 容器id # 停止当前正在运行的容器 docker kill 容器id # 强制停止当前容器
后台启动容器
# 命令 docker run -d 镜像命! [root@docker /]# docker run -d centos # 问题docker ps 的时候发现 centos 停止了 # 常见的坑,docker 容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止 # nginx, 容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了
容器内下载命令apt-get update & apt-get install -y
apt-get update & apt-get install -y iputils-ping (ping) apt-get update & apt-get install -y iproute2 (ip addr)
查看日志
docker logs -f -t --tail 容器,没有日志 # 自己编写一段shell脚本 [root@docker /]# docker run -d centos /bin/sh -c "while true;do echo kunjie;sleep 1;done" # [root@docker /]# docker ps CONTAINER ID IMAGE 697404d66604 centos # 显示日志 -tf # 显示日志 -- tail number(要显示多少日志就写多少) # 要显示的日志条数 [root@docker /]# docker logs -tf --tail 10 697404d66604
查看容器中进程信息ps
# 命令 docker top 容器id [root@docker /]# docker top 697404d66604 UID PID PPID C STIME TTY root 25658 25637 0 14:44 ? root 26828 25658 0 14:59 ?
查看镜像的元数据
# 命令 docker inspect 容器id # 测试 [root@docker /]# docker inspect 697404d66604 [ { "Id": "697404d6660486982c149dbe67700e26f72d138b8e742dd610ca636002170369", "Created": "2021-10-23T06:44:58.177717314Z", "Path": "/bin/sh", "Args": [ "-c", "while true;do echo kunjie;sleep 1;done" ], "State": { "Status": "running", "Running": true, "Paused": false, "Restarting": false, "OOMKilled": false, "Dead": false, "Pid": 25658, "ExitCode": 0, "Error": "", "StartedAt": "2021-10-23T06:44:58.51763967Z", "FinishedAt": "0001-01-01T00:00:00Z" }, "Image": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6", "ResolvConfPath": "/var/lib/docker/containers/697404d6660486982c149dbe67700e26f72d138b8e742dd610ca636002170369/resolv.conf", "HostnamePath": "/var/lib/docker/containers/697404d6660486982c149dbe67700e26f72d138b8e742dd610ca636002170369/hostname", "HostsPath": "/var/lib/docker/containers/697404d6660486982c149dbe67700e26f72d138b8e742dd610ca636002170369/hosts", "LogPath": "/var/lib/docker/containers/697404d6660486982c149dbe67700e26f72d138b8e742dd610ca636002170369/697404d6660486982c149dbe67700e26f72d138b8e742dd610ca636002170369-json.log", "Name": "/wonderful_hopper", "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/bfcc24e3476bc389bcbf03eca613bd5880e3c054b8ff0d1e4b714cdc39aec8a0-init/diff:/var/lib/docker/overlay2/69dfbd33b594e56380e21d68b02b607d8cd3b4e5a33040b0e082ff8f36835d51/diff", "MergedDir": "/var/lib/docker/overlay2/bfcc24e3476bc389bcbf03eca613bd5880e3c054b8ff0d1e4b714cdc39aec8a0/merged", "UpperDir": "/var/lib/docker/overlay2/bfcc24e3476bc389bcbf03eca613bd5880e3c054b8ff0d1e4b714cdc39aec8a0/diff", "WorkDir": "/var/lib/docker/overlay2/bfcc24e3476bc389bcbf03eca613bd5880e3c054b8ff0d1e4b714cdc39aec8a0/work" }, "Name": "overlay2" }, "Mounts": [], "Config": { "Hostname": "697404d66604", "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 kunjie;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": "9248e259635085346570b904dcae9cc75371e32e7ae36c4ea6a17a0136fcb9c1", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": {}, "SandboxKey": "/var/run/docker/netns/9248e2596350", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "e8aeac3e260cebfabd136b3b1e0de8dd76378636e5bb7f358a40cad5256a223c", "Gateway": "172.17.0.1", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "172.17.0.3", "IPPrefixLen": 16, "IPv6Gateway": "", "MacAddress": "02:42:ac:11:00:03", "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "4b9ffcfa9e464816c93c0a95d13c5bb8142ed62582e9b229b55af43fdf6dd38e", "EndpointID": "e8aeac3e260cebfabd136b3b1e0de8dd76378636e5bb7f358a40cad5256a223c", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.3", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:03", "DriverOpts": null } } } } ]
进入当前正在运行的容器
# 我们通常容器都是使用后台方式运行的,需要进入容器,修改一些配置 # 命令 docker exec -it 容器id bashShell(/bin/bash) # 测试 [root@docker /]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 697404d66604 centos "/bin/sh -c 'while t…" 33 minutes ago Up 33 minutes wonderful_hopper 9342159fc768 centos "/bin/bash" 38 minutes ago Up 38 minutes hopeful_jemison [root@docker /]# docker exec -it 697404d66604 /bin/bash [root@697404d66604 /]# ls bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var [root@697404d66604 /]# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 06:44 ? 00:00:00 /bin/sh -c while true;do echo kunjie;sleep 1;done root 2048 0 0 07:19 pts/0 00:00:00 /bin/bash root 2075 1 0 07:19 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1 root 2076 2048 5 07:19 pts/0 00:00:00 ps -ef # 方式二 docker attach 容器id # 测试 [root@docker /]# docker attach 697404d66604 正在执行当前的代码... # docker exec # 进入容器后开启一个新的终端,可以在里面操作(常用) # docker attach # 进入容器正在之心过的终端,不会启动新的进程!
从容器内拷贝文件到主机上
docker cp 容器id:容器内路径 目的的主机路径 # 查看当前主机目录下 [root@docker home]# ls harry kunjie.java oracle shikun xuegod xuegod2 xuegod3 [root@docker home]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 78e7f3269d31 centos "/bin/bash" About a minute ago Up About a minute adoring_kilby # 进入docker容器内部 [root@docker home]# docker attach 78e7f3269d31 [root@78e7f3269d31 /]# cd /home [root@78e7f3269d31 home]# ls # 在容器内新建一个文件 [root@78e7f3269d31 home]# touch test.java [root@78e7f3269d31 home]# ls test.java [root@78e7f3269d31 home]# exit exit [root@docker home]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [root@docker home]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 78e7f3269d31 centos "/bin/bash" 3 minutes ago Exited (0) 7 seconds ago adoring_kilby # 将文件拷贝出来到主机上 [root@docker home]# docker cp 78e7f3269d3:/home/test.java /home [root@docker home]# ls harry kunjie.java oracle shikun test.java xuegod xuegod2 xuegod3 [root@docker home]# # 拷贝是一个手动过程,未来我们使用 -v 卷的计数,可以实现 自动同步
Docker 安装 Nginx
# 1.搜索镜像 search 建议去docker搜索,可以看到帮助文档信息 # 2.下载镜像 pull # 3.运行测试 [root@docker home]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 87a94228f133 11 days ago 133MB centos latest 5d0da3dc9764 5 weeks ago 231MB # -d 代表后台运行 # --name 给容器命名 # -p 宿主机端口:容器内部端口 [root@docker home]# docker run -d --name nginx01 -p 3344:80 nginx d00c230bb729b8d3bd9c5bdab9dde5f23a31438267d1b99205101600882c19b5 [root@docker home]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d00c230bb729 nginx "/docker-entrypoint.…" 6 minutes ago Up 6 minutes 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01 [root@docker home]# curl localhost:3344 # 进入容器 [root@docker ~]# docker exec -it nginx01 /bin/bash root@d00c230bb729:/# whereis nginx nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx root@d00c230bb729:/# cd /etc/nginx root@d00c230bb729:/etc/nginx# ls conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params root@d00c230bb729:/etc/nginx#
端口暴露的概念
Docker 来装一个tomcat
# 官方的使用 docker run -it --rm tomcat:9.0 # 我们之前的启动都是后台,停止了容器之后,容器还是可以查到的 docker run -it --rm tomcat:9.0 一半用来测试,用完即删 # 下载在启动 docker pull tomcat # 启动运行 docker run -d -p 3355:8080 --name tomcat01 tomcat # 测试访问没有问题 # 进入容器 [root@docker /]# docker exec -it tomcat01 /bin/bash # 发现问题:1.Linux命令少了, 2.没有webapps。 阿里云镜像的原因,默认是最小的镜像,所有的不必要的都剔除掉 # 保证最小可运行的环境!
部署ES + Kibana
# 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 # 启动了 linux就非常卡 docker stats 查看cup状态 # es 是十分高内存的 一启动就是1G 现在服务器只有1核2G # 查看 docker stats # 测试一个es是否成功了 [root@docker /]# curl localhost:9200 { "name" : "1251736a2370", "cluster_name" : "docker-cluster", "cluster_uuid" : "AI4kes9nTjOyPMXTFh71kA", "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 环境配置修改 docker run -d --name elasticsearch02 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPST="-Xms64m -Xms512m" elasticsearch:7.6.2 # 查看 docker stats
[root@docker /]# curl localhost:9200 { "name" : "beb40ea6115d", "cluster_name" : "docker-cluster", "cluster_uuid" : "ZgQDZ4GeTAuSF4C8AAAsmQ", "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" }
使用kibana连接es?网络如何才能连接过去
portainer(先用这个)
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 run -d -p 8088:9000 \ --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
下载完成访问测试一下:外网 8088
http://172.16.1.23:8088/ 通过他来访问
镜像是一种轻量级,可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包含代码,运行时,库,环境变量配置文件。
所有的应用,直接打包成为一个docker镜像,就可以直接跑起来!
如何得到镜像:
从远程仓库下载
朋友拷贝给你
自己制作一个镜像 DockerFile
UnionFS(联合文件系统)
我们下载的时候看到的一层层就是这个!
UnionFS(联合文件系统):Union文件系统(UnioFS)是一种分层,轻量级并且高性能的文件系统它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union文件系统是Docker镜像的基础,镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
Docker镜像加载原理
docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统就是UnionFS(联合文件系统)。
bootfs(boof file system)主要包含bootloader和kernel,bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层时botfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核,当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
rootfs (root file system),在bootfs之上。包含的就是典型Liunx系统中的/dev,/proc,/bin,/etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如buntu,Centos等等。
平时我们安装进虚拟机的CnetOS都是好几个G,为什么Docker这里才200M?
对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了,由此可见对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs。这也是为什么docker的centos这里才204MB的原因
虚拟机是分钟级别,容器是秒级!
分层的镜像
我们可以去下载一个镜像,注意观察下载的日志输出。可以看到是一层一层的在下载!
为什么Docker镜像要采用这种分层的结构呢
最大的好处,莫过于是资源共享了!比如由多个镜像都从相同过的Base镜像构建而来,那么宿主机只需要在磁盘上保留鱼粉base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。
查看镜像分层的方式可以通过 docker image inspetc命令 !
[root@docker ~]# docker image inspect redis:latest [ // ..... "RootFS": { "Type": "layers", "Layers": [ "sha256:e8b689711f21f9301c40bf2131ce1a1905c3aa09def1de5ec43cf0adf652576e", "sha256:b43651130521eb89ffc3234909373dc42557557b3a6609b9fed183abaa0c4085", "sha256:8b9770153666c1eef1bc685abfc407242d31e34f180ad0e36aff1a7feaeb3d9c", "sha256:6b01cc47a390133785a4dd0d161de0cb333fe72e541d1618829353410c4facef", "sha256:0bd13b42de4de0a0d0cc3f1f162cd0d4b8cb4ee20cbea7302164fdc6894955fd", "sha256:146262eb38412d6eb44be1710bfe0f05d3493831f82b1c2be8dc8d9558c9f033" ] }, "Metadata": { "LastTagTime": "0001-01-01T00:00:00Z" } } ]
特点
Docker镜像都是默认只读的,当容器启动时,我们就加一个新的镜像,一个新的可写层被加载到镜像的顶部!
这一层就是我们通常说的容器曾,容器之下的都叫镜像层!
如何提交一个自己的镜像
docker commit 提交容器称为一个新的副本 # 命令和git原理类似 # 提交镜像的命令 docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG](版本)
实战测试
# 1,启动一个默认的tomcat # 2,发现这个默认的tomcat 是没有webapps应用, 镜像的原因,官方的镜像默认 webapps下面时没有文件的! # 3,自己拷贝进去了基本的文件 # 4,将我们操作过的容器通过commit提交为一个镜像!我们以后就使用我们修改过的镜像即可,这就是我们自己的一个修改的镜像。
如果你想要保存当前的容器的状态,就可以通过commit来提交,获得一个镜像,就好比VM的快照!
docker的理念回顾
将应用和环境打包成一个镜像!
数据?如果数据都在容器i中,那么我们容器删除,数据就会丢失!需求:数据可以持久化
MySQL,容器删除了,数据也就删除了,就相当于删库!需求:MySQL数据可以存储在本地!
容器之间可以有一个数据共享的计数!Docker容器中产生的数据,同步到本地!
这就是卷技术!就相当于目录的挂载,将我们容器内的目录,挂载在Liunx上面!
容器的持久化和同步操作!容器间也是可以数据共享的!
方式一:直接使用命令来挂载 -v
docker run -it -v 主机目录,容器内目录 # 测试 [root@docker home]# docker run -it -v /home/ceshi:/home centos /bin/bash # 启动起来时我们可以通过 docker inspect 容器id 查看详细信息
测试文件的同步
再来测试
1,停止容器
2,宿主上修改文件
3,启动容器,
4,容器内的数据依旧是同步的
我们以后修改只需要在本地修改即可,容器内会自动同步!
思考:MySQL的数据持久化的问题!
# 获取镜像 [root@docker home]# docker pull mysql:5.7 # 运行容器,需要做数据挂载! # 安装启动MySQL,注意需要配置密码! # 官方测试:docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag # 启动我们的 -d 后台运行 -p 端口映射,暴露端口 -v 卷挂载 -e 环境配置 -- name 容器名字 [root@docker home]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7 # 启动成功之后,我们在本地使用 sqlyog 来测试连接一下 # sqlyog-连接到服务器的3310 3310 和容器内的 3306映射,这个时候我们就可以连接上了! # 在本地测试创建一个数据库,查看一下我们映射的路径是否ok!
如果我们将容器删除
再看宿主机 我们挂载到本地的数据卷依旧没有丢失,这就实现了容器数据持久化功能!
# 匿名挂载 -v 容器内路径 docker run -d -p --name nginx01 -v /etc/nginx nginx # 查看所有的 volume 的情况 [root@docker ~]# docker volume ls DRIVER VOLUME NAME local 6585ff04b4a8fa1f9bf9d0f55c7ff92c6f5ea29e02e179ef7dcfd1169501419c # 这里发现,这种就事匿名挂载,我们在 -v 只写了容器内的路径,没有写容器外的路径! # 具名挂载 [root@docker ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx 6429a125eddc69a4ac29425ca45cfbae7174e26fa9def64e23fe24b17b312642 [root@docker ~]# docker volume ls DRIVER VOLUME NAME local juming-nginx # 通过 -v 卷名:容器内路径 # 查看一下这个卷
所有的docker容器内的卷,没有指定目录的情况下都是在./var/lib/docker/volumes/xxxxxx/_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 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部无法操作
Dockerfile 就是用来构建 docker 镜像的构建文件 ! 命令脚本!
通过这个脚本可以生成镜像,镜像是一层一层的,简本是一个个的命令,每个命令都是一层!
# 创建一个dockerfile文件,名字可以随机 建议 Dockerfile # 文件中的内容 指令(大写) 参数 FROM centos VOLUME ["volume01","volume02"] CMD echo "---end---" CMD /bin/bash # 这里的每个命令,就是镜像的一层!
# 启动自己写的容器
这个卷一定和外面有一个同步的目录
查看一下卷挂载的路径
在容器上创建文件
在宿主机上测试一下刚才的文件是否同步出去了
这种方式我们未来使用的十分多,因为我们通常会构建自己的镜像!
假设构建镜像时候没有挂载卷,要手动镜像挂载 -v 卷名:容器内路径!
多个 MySQL 同步数据
# 启动三个容器,通过我们刚才自己的镜像启动
# 测试:可以删除docker01,查看一下docker02和docker03是否还可以访问这个文件 # 测试成功依旧可以访问
多个MySQL实现数据共享
[root@docker home]# docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7 [root@docker home]# docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7 # 这个时候,可以实现两个容器数据同步
结论:
容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。
但是一但你持久化到了本地,这个时候,本地的数据是不会删除的!
dockerfile 是用来构建docker镜像的文件!命令参数脚本!
构建步骤:
编写一个dockerfile 文件
docker build 构建成为一个镜像
docker run 运行镜像
docker push 发布镜像 (Docker Hub,阿里云镜像仓库!)
查看一下官方是怎么做的
基础知识:
每个保留关键字(指令)都是必须是大写字母
执行从上到下顺序执行
#表示注释
每一个指令都会创建提交一个新的镜像层,并提交!
步骤:开发,部署,运维
DockerFile:构建文件,定义了一切的步骤,源代码
Dockerimages:通过DockerFile 构建生成的镜像,最终发布和运行的产品!
Docker容器:容器就是镜像运行起来提供服务器
FROM # 基础镜像,一切从这里开始构建 MAINTAINER # 镜像是谁写的,姓名+邮箱 RUN # 镜像构建的时候需要运行的命令 ADD # 步骤:tomcat镜像,这个tomcat压缩包!添加内容 WROKDIR # 镜像的工作目录 VOLUME # 挂载的目录 EXPOSE # 暴露端口配置 CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代 ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令 ONBUTLD # 当构建一个被继承 DockerFile 这个时候就会运行 ONBUTLD 的指令,出发指令 COPY # 类似ADD,将我们文件拷贝到镜像中 ENV # 构建的时候设置环境变量
Docker Hub 中99%镜像都是从这个基础镜像过来的 FROM scratch,然后配置需要的软件和配置来进行构建
创建一个自己的centos
# 1. 编写DockerFile的文件 [root@docker dockerfile]# cat mydockerfile-centos FROM centos MAINTAINER kunjie<1813820709@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 dockerfile文件路径 -t 镜像命:[tag] Successfully built c83feb249546 Successfully tagged mycentos:0.1 # 3. 测试运行
对比:之前的原生的centos
我们增加之后的镜像
我们可以列出本地镜像的变更历史
CMD 和 ENTRYPOINT 的区别
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代 ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
测试cmd
# 编写 dockerfile 文件 [root@docker dockerfile]# cat dockerfile-cmd-test FROM centos CMD ["ls","-a"] # 构建镜像buile [root@docker dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest . # run运行,发现我们的ls -a生效了 [root@docker dockerfile]# docker run cmdtest . .. .dockerenv bin dev etc home lib # 想追加一个命令 -l 我所期望他给我返回的是 ls -al展示列表的详细数据 但是你会发现他报错 [root@docker dockerfile]# docker run cmdtest -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[0000] error waiting for container: context canceled # CMD的情况下 -l 替换了CMD ["ls","-a"] 命令,-l 不是命令所以报错!
测试ENTRYPOINT
[root@docker dockerfile]# vim dockerfile-cmd-entrypoint [root@docker dockerfile]# docker build -f dockerfile-cmd-entrypoint -t entrypoint-test . Sending build context to Docker daemon 4.096kB Step 1/2 : FROM centos ---> 5d0da3dc9764 Step 2/2 : ENTRYPOINT ["ls","-a"] ---> Running in 53556b68b305 Removing intermediate container 53556b68b305 ---> 6502c3b57a71 Successfully built 6502c3b57a71 Successfully tagged entrypoint-test:latest [root@docker dockerfile]# docker run entrypoint-test . .. .dockerenv bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var # 我们的追加命令,是直接拼接在我们的 ENTRYPOINT 命令的后面的 [root@docker dockerfile]# docker run entrypoint-test -l total 0 drwxr-xr-x. 1 root root 6 Nov 9 02:26 . drwxr-xr-x. 1 root root 6 Nov 9 02:26 .. -rwxr-xr-x. 1 root root 0 Nov 9 02:26 .dockerenv lrwxrwxrwx. 1 root root 7 Nov 3 2020 bin -> usr/bin drwxr-xr-x. 5 root root 340 Nov 9 02:26 dev drwxr-xr-x. 1 root root 66 Nov 9 02:26 etc drwxr-xr-x. 2 root root 6 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 6 Sep 15 14:17 lost+found drwxr-xr-x. 2 root root 6 Nov 3 2020 media drwxr-xr-x. 2 root root 6 Nov 3 2020 mnt drwxr-xr-x. 2 root root 6 Nov 3 2020 opt dr-xr-xr-x. 292 root root 0 Nov 9 02:26 proc dr-xr-x---. 2 root root 162 Sep 15 14:17 root drwxr-xr-x. 11 root root 163 Sep 15 14:17 run lrwxrwxrwx. 1 root root 8 Nov 3 2020 sbin -> usr/sbin drwxr-xr-x. 2 root root 6 Nov 3 2020 srv dr-xr-xr-x. 13 root root 0 Nov 9 01:44 sys drwxrwxrwt. 7 root root 171 Sep 15 14:17 tmp drwxr-xr-x. 12 root root 144 Sep 15 14:17 usr drwxr-xr-x. 20 root root 262 Sep 15 14:17 var
准备镜像文件 tomcat 压缩包,jdk的压缩包
编写dockerfile文件,官方命名 Dockerfile , build 会自动寻找这个文件,就不需要 -f 指定了 !
FROM centos MAINTAINER kunjie<1813820709@qq.com> COPY readme.txt /usr/local/readme.txt ADD jdk-11.0.13_linux-x64_bin.tar.gz /usr/local/ ADD apache-tomcat-9.0.54.tar.gz /usr/local/ RUN yum -y install vim ENV MYPATH /usr/local WORKDIR $MYPATH ENV JAVA_HOME /usr/local/jdk11.0.13 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.54 ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.54 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin EXPOSE 8080 CMD /usr/local/apache-tomcat-9.0.54/bin/startup.sh && tail -F /url/local/apache-tomcat-9.0.54/bin/logs/catalina.out
构建镜像
# docker build -t diytomcat .
启动镜像
访问测试
发布项目(由于做了卷挂载,我们直接在本地编写项目就可以发布了!)
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>db</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> </web-app>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>hello,kunjie</title> </head> <body> Hello World!<br/> <% Systeml.out.println("----my test web logs----"); %> </body> </html>
项目部署成功,可以直接访问
DockerHub
地址Docker Hub 注册自己的账号!
确定这个账号可以登录
在我们服务器上提交自己的镜像
[root@docker tomcat]# 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@docker tomcat]# docker login -u shikunjie 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
登录完毕后就可以提交镜像了,就是一步 docker push
# push自己的镜像到服务器上 [root@docker tomcat]# docker push diytomcat Using default tag: latest The push refers to repository [docker.io/library/diytomcat] 76d18c77b942: Preparing af5703db4169: Preparing d7ea5969d930: Preparing 4b85eb6e14af: Preparing 74ddd0ec08fa: Preparing denied: requested access to the resource is denied # 拒绝 # push镜像的问题? [root@docker tomcat]# docker push shikunjie/diytomcat:1.0 The push refers to repository [docker.io/shikunjie/diytomcat] An image does not exist locally with the tag: shikunjie/diytomcat # 解决,增加一个 tag(版本号) [root@docker tomcat]# docker tag 3d0e7823b8d9 shikunjie/tomcat:1.0 # docker push 上去即可,自己发布的镜像尽量带上 [root@docker tomcat]# docker push shikunjie/tomcat:1.0 The push refers to repository [docker.io/shikunjie/tomcat] 76d18c77b942: Pushed af5703db4169: Pushed d7ea5969d930: Pushed 4b85eb6e14af: Pushed 74ddd0ec08fa: Pushed 1.0: digest: sha256:ee132789da4b2316e4f8cdfa36e10760d5d1d4544fdb0cbd6e7e8fb85369f33a size: 1373
提交的时候也是按照镜像的层级来进行提交的!
发布到阿里云镜像服务上
登录阿里云
找到容器镜像服务
创建命名空间
创建容器镜像
浏览阿里云
阿里云容器镜像的就参考官方地址!
清空所有环境
测试
# 问题:docker 是如何处理容器网络访问的?
# [root@docker ~]# docker run -d -P --name tomcat01 tomcat # 查看容器的内部网络地址 ip addr , 发现容器启动的时候会得到一个 eth0@if10 ip地址, docker分配的 [root@docker ~]# docker exec -it tomcat01 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 9: eth0@if10: <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 # liunx 能不能 ping 通容器内部 [root@docker /]# ping 172.17.0.2 PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data. 64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.064 ms 64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.076 ms # linux 可以ping 通 docker 容器内部
原理
我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0桥接模式,使用的技术是evth-pair 技术!
再次测试 ip addr
在启动一个容器测试,发现又多了一对网卡
# 我们发现这个容器带来的网卡,都是一对一对的 # evth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一端连着协议,一端彼此相连 # 正因为有这个特性,evth-pair 充当一个桥梁,连接各种虚拟网络设备的 # OpenStac(这是以前学的), Docker 容器之间的连接,OVS的连接,都是使用的 evth-pair 技术
测试一下 tomcat01和 tomcat02是否可以ping通!
[root@docker /]# docker exec -it tomcat02 ping 172.17.0.2 PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data. 64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.213 ms 64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.047 ms # 结论:容器和容器之间是可以互相ping通的
网络模型图:
结论:tomcat01 和 tomcat02 是公用的一个路由器,也就是docker0.
所有的容器不指定网络的情况下,都是docker0路由的,docker会给我们的容器分配一个默认的可用IP
小结
Docker 中的所有的网络接口都是虚拟的,虚拟的转发效率高!(内网传递文件)!
只要容器删除对应的veth网桥也就没了!
######
思考一个场景,我们编写了一个微服务,database url=ip:,项目不重启,数据库ip换掉了,我们希望可以处理这个问题,可以用名字来访问容器
[root@docker /]# docker exec -it tomcat02 ping tomcat01 ping: tomcat01: Name or service not known # 如何解决呢? [root@docker /]# docker run -d -P --name tomcat03 --link tomcat02 tomcat [root@docker /]# docker exec -it tomcat03 ping tomcat02 PING tomcat02 (172.17.0.3) 56(84) bytes of data. 64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.056 ms 64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.049 ms # 反向不可以ping通 [root@docker /]# docker exec -it tomcat02 ping tomcat03 ping: tomcat03: Name or service not known
本质探究:--link 就是我们在hosts配置中增加了一些歌172.18.0.3 tomcat02
我们现在玩Docker 已经不建议使用 --link了
使用自定义网络! 不适用docker0!
docker0问题:他不支持容器名连接访问!
查看所有的docker网络
网络模式
bridge : 桥接 docker (默认,自己创建也使用bridge 模式)
none : 不配置网络
host : 和宿主机共享网络
container : 容器内可以网络连通! (用得少!局限很大)
# docker0特点,默认,域名不能访问, --link可以打通连接! # 我们可以自定义一个网络! # --driver bridge # --subnet 192.168.0.0/16 # --gateway 192.168.0.1 [root@docker ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet 7deef8178eef8b9a9e8bcdcf3400c60e8ca35ba7d35f6c66d45b933fa7d5a4b0 [root@docker ~]# docker network ls NETWORK ID NAME DRIVER SCOPE c699015536d2 bridge bridge local 195ae44fa95a host host local 7deef8178eef mynet bridge local 82568a72415c none null local
我们自己的网络就创建好了
[root@docker /]# docker run -d -P --name tomcat-net-01 --net mynet tomcat 5f84191cc0c36c0f67e746e9679be2670165104a35e9fb098c67ca5bc9220512 ^[[A^[[D[root@docker /]# docker run -d -P --name tomcat-net-01 --net mynet tomc^C [root@docker /]# docker run -d -P --name tomcat-net-02 --net mynet tomcat 75b619e57465c0370e884a0d3cdeeb5d058729a7fac244dcf3321b941c84cc55 [root@docker /]# docker network inspect mynet [ { "Name": "mynet", "Id": "7deef8178eef8b9a9e8bcdcf3400c60e8ca35ba7d35f6c66d45b933fa7d5a4b0", "Created": "2021-11-17T09:48:20.757511431+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": { "5f84191cc0c36c0f67e746e9679be2670165104a35e9fb098c67ca5bc9220512": { "Name": "tomcat-net-01", "EndpointID": "cc9bee43edb65793ffa1ef4c4466b1215f2a8c44f169cf691d9fede8f3177503", "MacAddress": "02:42:c0:a8:00:02", "IPv4Address": "192.168.0.2/16", "IPv6Address": "" }, "75b619e57465c0370e884a0d3cdeeb5d058729a7fac244dcf3321b941c84cc55": { "Name": "tomcat-net-02", "EndpointID": "f3dab3747ebb7e860cb664cf342b69ae42467d414e3a5553c9f052eab7313d47", "MacAddress": "02:42:c0:a8:00:03", "IPv4Address": "192.168.0.3/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ] [root@docker /]# 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.067 ms 64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.052 ms 64 bytes from 192.168.0.3: icmp_seq=3 ttl=64 time=0.053 ms ^C --- 192.168.0.3 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2000ms rtt min/avg/max/mdev = 0.052/0.057/0.067/0.006 ms # 现在不使用 --link也可以ping 通名字了 [root@docker /]# 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.045 ms 64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.061 ms
我们自定义的网络docker都已经帮我们维护好了对应的关系,推荐我们平时这样使用网络!
好处:
redis:不同的集群使用不同的网络,保证集群是安全和健康的
MySQL:不同的集群使用不同的网络,保证集群是安全和健康的
# 测试打通 tomcat01 - mynet [root@docker /]# docker network connect mynet tomcat01 # 连通之后就是将 tomcat01 放到了mynet网络下 # 这个东西在官方叫一个容器两个ip地址 # 就好比阿里云服务器 一个 公网ip 一个私网ip
# 01 连通ok [root@docker /]# 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.137 ms 64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.060 ms # 02 依旧不行 因为02没有connect [root@docker /]# docker exec -it tomcat02 ping tomcat-net-02 ping: tomcat-net-02: Name or service not known
假设要跨网络操作别人,就需要使用 docker network connect 连通!
shell脚本!
# 创建网卡 docker network create redis --subnet 172.38.0.0/16 # 通过脚本创建留个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 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; \ docker run -p 6371:6379 -p 16371:16379 --name redis-1 \ -v /mydata/redis/node-1/data:/data \ -v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf docker run -p 6372:6379 -p 16372:16379 --name redis-2 \ -v /mydata/redis/node-2/data:/data \ -v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf docker run -p 6373:6379 -p 16373:16379 --name redis-3 \ -v /mydata/redis/node-3/data:/data \ -v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf docker run -p 6374:6379 -p 16374:16379 --name redis-4 \ -v /mydata/redis/node-4/data:/data \ -v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf docker run -p 6375:6379 -p 16375:16379 --name redis-5 \ -v /mydata/redis/node-5/data:/data \ -v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip 172.38.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf docker run -p 6376:6379 -p 16376:16379 --name redis-6 \ -v /mydata/redis/node-6/data:/data \ -v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf # 创建集群 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: 1d9674922751745737f50ff86a52847320b057c6 172.38.0.11:6379 slots:[0-5460] (5461 slots) master M: b80e1617bbec01b771864a70e7764cba16df0dd4 172.38.0.12:6379 slots:[5461-10922] (5462 slots) master M: 94227a4762bf040bad6182d6bd1ef73c11fce880 172.38.0.13:6379 slots:[10923-16383] (5461 slots) master S: 5b7872fa08b6f45cbd7469cc7c38619f25157602 172.38.0.14:6379 replicates 94227a4762bf040bad6182d6bd1ef73c11fce880 S: 0e346c433e362becdd2fecf487d1466601f15acd 172.38.0.15:6379 replicates 1d9674922751745737f50ff86a52847320b057c6 S: 1103db4cb33a1ef4b205e562f066c823fd5112cc 172.38.0.16:6379 replicates b80e1617bbec01b771864a70e7764cba16df0dd4 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: 1d9674922751745737f50ff86a52847320b057c6 172.38.0.11:6379 slots:[0-5460] (5461 slots) master 1 additional replica(s) M: b80e1617bbec01b771864a70e7764cba16df0dd4 172.38.0.12:6379 slots:[5461-10922] (5462 slots) master 1 additional replica(s) S: 1103db4cb33a1ef4b205e562f066c823fd5112cc 172.38.0.16:6379 slots: (0 slots) slave replicates b80e1617bbec01b771864a70e7764cba16df0dd4 S: 5b7872fa08b6f45cbd7469cc7c38619f25157602 172.38.0.14:6379 slots: (0 slots) slave replicates 94227a4762bf040bad6182d6bd1ef73c11fce880 M: 94227a4762bf040bad6182d6bd1ef73c11fce880 172.38.0.13:6379 slots:[10923-16383] (5461 slots) master 1 additional replica(s) S: 0e346c433e362becdd2fecf487d1466601f15acd 172.38.0.15:6379 slots: (0 slots) slave replicates 1d9674922751745737f50ff86a52847320b057c6 [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. # 连接集群 /data # redis-cli -c # 查看信息 cluster info 127.0.0.1:6379> cluster info cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:3 cluster_current_epoch:6 cluster_my_epoch:1 cluster_stats_messages_ping_sent:451 cluster_stats_messages_pong_sent:471 cluster_stats_messages_sent:922 cluster_stats_messages_ping_received:466 cluster_stats_messages_pong_received:451 cluster_stats_messages_meet_received:5 cluster_stats_messages_received:922 # 查看连接点 cluster nodes 127.0.0.1:6379> cluster nodes 38741bf6fd5bea71e756e4ff6440cf337643f336 172.38.0.15:6379@16379 slave adb3d90d72242b22f049229928fc09644cdd35e0 0 1637224059710 5 connected 7dd85d282b2ffc16a5ff9c72ca9434dd1a9750ae 172.38.0.12:6379@16379 master - 0 1637224059000 2 connected 5461-10922 72a0d139a34be8f6229bae9e68903083ac02bc1e 172.38.0.13:6379@16379 master - 0 1637224059000 3 connected 10923-16383 7c8fbcf6b4d56179867e0cbaeb56ab4234bff3c8 172.38.0.14:6379@16379 slave 72a0d139a34be8f6229bae9e68903083ac02bc1e 0 1637224058601 4 connected adb3d90d72242b22f049229928fc09644cdd35e0 172.38.0.11:6379@16379 myself,master - 0 1637224057000 1 connected 0-5460 8ac2cd76be864f922d0c4010802ca30ea3ead275 172.38.0.16:6379@16379 slave 7dd85d282b2ffc16a5ff9c72ca9434dd1a9750ae 0 1637224059000 6 connected
docker搭建redis集群完成!
我们使用给的docker之后,所有的技术都会慢慢的变得简单起来!
构架springboot项目
打包应用
编写dockerfile
构建镜像
发布运行
Docker
DockerFile build run 手动操作,单个容器!
微服务,100个微服务!依赖关系。
Docker Compose 来轻松高效的管理容器,定义运行多个容器
官方介绍
定义,运行多个容器
YAML file 配置文件。
single command。 命令有哪些?
Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration. To learn more about all the features of Compose, see the list of features.
所有的环境都可以使用Compose
Compose works in all environments: production, staging, development, testing, as well as CI workflows. You can learn more abo ut each case in Common Use Cases.
三步骤
Using Compose is basically a three-step process:
Define your app’s environment with a Dockerfile
so it can be reproduced anywhere.
Dockerfile 保证我们的项目在任何地方可以运行
Define the services that make up your app in docker-compose.yml
so they can be run together in an isolated environment.
services 什么事服务。
docker-compose.yml这个文件怎么写!
Run docker compose up
and the Docker compose command starts and runs your entire app. You can alternatively run docker-compose up
using the docker-compose binary.
启动项目
作用:批量容器编排
理解
Compose是Docker官方的开源项目,需要安装
Dockerfile
让程序在任何地方运行。web服务,redis,mysql,nginx ... 多个容器 run
Compose
version: "3.9" # optional since v1.27.0 services: web: build: . ports: - "5000:5000" volumes: - .:/code - logvolume01:/var/log links: - redis redis: image: redis volumes: logvolume01: {}
docker-compose up 哪怕你有100个服务,也可以一键上线
Compose:重要的概念
服务services,容器,应用。(web,redis,mysql....)
项目project。一组关联的容器。博客。web,mysql。
1.下载
# 官网这个网络十分满,有可能还下载失败! sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose # 这个可能快点! curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.5/docler-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose # 如果第一步没有下载下来,我们就手动去网站在下载即可! # 地址:https://github.com/docker/compose/releases # 下载:docker-compose-Linux-x86_64 # 然后将文件上传到 /usr/local/bin/ 文件夹下,然后将其重命名为docker-compose # 第二步:修改此文件的权限,增加可执行 sudo chmod +x /usr/local/bin/docker-compose # 版本信息 docker-compose version
授权,修改此文件的权限,增加可执行
sudo chmod +x /usr/local/bin/docker-compose
多看官网。。。。
地址:Get started with Docker Compose | Docker Documentation
Python应用。计数器。redis!
应用 app.py
Dockerfile 应用打包为镜像
Docker-compose yaml文件 (定义整个服务,需要的环境,web,redis)
启动 compose 项目 (docker-compose up)
流程:
创建网络
执行Docker-compose yaml
启动服务
Docker-compose yaml
Starting composetest_redis_1 ... done Starting composetest_web_1 ... done
文件名 composetest
服务
version: "3.9" services: web: build: . ports: - "5000:5000" redis: image: "redis:alpine"
准备工作
yum install python-pip # pip 是 Ptyhon 包管理工具 yum -y install epel-release # 报错的话执行
为项目创建目录
mkdir composetest cd composetest
在项目目录中创建一个名为app.py的文件,内容如下:
import time import redis from flask import Flask app = Flask(__name__) cache = redis.Redis(host='redis', port=6379) def get_hit_count(): retries = 5 while True: try: return cache.incr('hits') except redis.exceptions.ConnectionError as exc: if retries == 0: raise exc retries -= 1 time.sleep(0.5) @app.route('/') def hello(): count = get_hit_count() return 'Hello World! I have been seen {} times.\n'.format(count) if __name__ == "__main__": app.run(host="0.0.0.0", debug=True)
在本例中,redis是应用程序网络上redis容器的主机名,我们使用Redis的默认端口6379
在项目目录中创建另一个名为requirements.txt的文件,内容
flask redis
在项目目录中,创建名为Dockerfile的文件:
FROM python:3.6-alpine ADD . /code WORKDIR /code RUN pip install -r requirements.txt CMD ["python", "app.py"] # 这告诉Docker: # 从Python 3.6影响开始构建镜像 # 将当前目录添加到/code映像中的路径中。 # 将工作目录设置为/code # 安装Python依赖项 # 将容器的默认命令设置为python app.py
在项目目录中创建一个名为docker-compose.yml的文件:
version: "3.8" services: web: build: . ports: - "5000:5000" volumes: - .:/code redis: image: "redis:alpine"
自动的默认规则
docker images
[root@docker ~]# docker service ls Error response from daemon: This node is not a swarm manager. Use "docker swarm init" or "docker swarm join" to connect this node to swarm and try again.
默认的服务名 文件名 _ 服务名 _ num
多个服务器。集群 A B _num 副本数量
服务redis服务 => 4个副本
集群状态,服务都不可能只有一个运行实例。真实的项目一定是弹性的 10 HA 高并发
kubectl service 负载均衡
网络规则
只要我们同意compose启动 就会自动生成一个compose网络
比如说使用docker运行10个服务=> 项目 (项目中给的内容都在同个网络下,域名访问)
如果在同一个网络下,我们可以直接通过域名访问、
HA!
停止:docker-compose down ctrl+c
docker-compose
以前都是单个 docker run 启动容器
现在使用了docker-compose可以通过docker-compose编写 yaml配置文件 ,可以通过compose一键启动所有服务,或者停止
docker小结:
1、Docker镜像。run=>容器
2、DockerFile 构建镜像 (服务打包)
3、docker-compose 启动项目 (编排、多个微服务/环境)
4、Docker网络!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。