【狂神说Java】Docker最新超详细版教程通俗易懂
视频地址:https://www.bilibili.com/video/BV1og4y1q7M4?share_source=copy_web
Docker安装
基本组成
说明:
-
镜像(image):
docker镜像好比一个模板,可以通过这个模板来创建容器服务,tomcat镜像 ==> run ==> tomcat01容器(提供服务器),通过这个镜像可以创建多个容器,最终服务运行或者项目运行就是在容器中的。
-
容器(container):
docker利用容器技术,独立运行一个或者一组应用,通过镜像来创建
基本命令:启动,停止,删除
目前可以把这个容器理解为就是一个简易的 linux 系统
-
仓库(repository):
仓库就是存放镜像的地方。仓库分为公有仓库和私有仓库,Docker Hub(默认是国外的)
安装Docker
环境查看
# 系统内核是 3.10 以上的
[root@localhost /]# uname -r
3.10.0-1160.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"
安装
-
卸载旧的版本
yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine
-
需要的安装包
yum install -y yum-utils
-
设置镜像的仓库
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 #推荐使用阿里云
-
更新yum软件包索引
yum makecache fast
-
安装docker docker-ce 社区 docker-ee 企业
yum install docker-ce docker-ce-cli containerd.io
-
启动docker
[root@localhost /]# systemctl start docker # 启动 [root@localhost /]# docker version # 查看 Client: Docker Engine - Community Version: 20.10.11 API version: 1.41 Go version: go1.16.9 Git commit: dea9396 Built: Thu Nov 18 00:38:53 2021 OS/Arch: linux/amd64 Context: default Experimental: true Server: Docker Engine - Community Engine: Version: 20.10.11 API version: 1.41 (minimum version 1.12) Go version: go1.16.9 Git commit: 847da18 Built: Thu Nov 18 00:37:17 2021 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.4.12 GitCommit: 7b11cfaabd73bb80907dd23182b9347b4245eb5d runc: Version: 1.0.2 GitCommit: v1.0.2-0-g52b36a2 docker-init: Version: 0.19.0 GitCommit: de40ad0
-
hello-world
[root@localhost /]# docker run hello-world 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/
-
查看镜像
[root@localhost /]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest feb5d9fea6a5 2 months ago 13.3kB
-
卸载docker
# 卸载依赖 [root@localhost /]# yum remove docker-ce docker-ce-cli containerd.io # 删除资源 [root@localhost /]# rm -rf /var/lib/docker [root@localhost /]# rm -rf /var/lib/containerd
配置阿里云镜像加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://axvfsf7e.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
Hello World
run 的流程和docker原理
Docker常用命令
基础命令
docker version # 显示docker的版本信息
docker info # 显示docker的系统信息,包括镜像和容器的数量
docker 命令 --help # 帮助命令
帮助文档地址:https://docs.docker.com/engine/reference/commandline/
镜像命令
-
docker image
:查看所有本机上的镜像[root@localhost /]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest feb5d9fea6a5 2 months ago 13.3kB # 解释 REPOSITORY 镜像的仓库源 TAG 镜像的标签 IMAGE ID 镜像的ID CREATED 镜像的创建时间 SIZE 镜像的大小 # 可选项 Options: -a, --all # 列出所有的镜像 -q, --quiet # 只显示镜像的ID
-
docker search
:搜索镜像[root@localhost /]# docker search mysql NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-source relation… 11741 [OK] mariadb MariaDB Server is a high performing open sou… 4476 [OK] # 可选项 --filter=STARS=5000 # 过滤STARS大于5000的 [root@localhost /]# docker search mysql --filter=STARS=5000 NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-source relation… 11741 [OK]
-
docker pull
:下载镜像,docker pull imageName [:tag]
[root@localhost /]# docker pull mysql # 不写tag,默认就是 latest Using default tag: latest latest: Pulling from library/mysql a10c77af2613: Pull complete # 分层下载,docker image的核心(联合文件系统) b76a7eb51ffd: Pull complete 258223f927e4: Pull complete 2d2c75386df9: Pull complete 63e92e4046c9: Pull complete f5845c731544: Pull complete bd0401123a9b: Pull complete 3ef07ec35f1a: Pull complete c93a31315089: Pull complete 3349ed800d44: Pull complete 6d01857ca4c1: Pull complete 4cc13890eda8: Pull complete Digest: sha256:aeecae58035f3868bf4f00e5fc623630d8b438db9d05f4d8c6538deb14d4c31b # 签名 Status: Downloaded newer image for mysql:latest docker.io/library/mysql:latest # 真实地址 # 等价 docker pull mysql docker pull docker.io/library/mysql:latest # 指定版本下载 [root@localhost ~]# docker pull mysql:5.7 5.7: Pulling from library/mysql a10c77af2613: Already exists # 已经存在的不再下载 b76a7eb51ffd: Already exists 258223f927e4: Already exists 2d2c75386df9: Already exists 63e92e4046c9: Already exists f5845c731544: Already exists bd0401123a9b: Already exists 2724b2da64fd: Pull complete d10a7e9e325c: Pull complete 1c5fd9c3683d: Pull complete 2e35f83a12e9: Pull complete Digest: sha256:7a3a7b7a29e6fbff433c339fc52245435fa2c308586481f2f92ab1df239d6a29 Status: Downloaded newer image for mysql:5.7 docker.io/library/mysql:5.7 # 查看镜像 [root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mysql 5.7 8b43c6af2ad0 11 days ago 448MB mysql latest b05128b000dd 11 days ago 516MB hello-world latest feb5d9fea6a5 2 months ago 13.3kB
-
docker rmi
:删除镜像[root@localhost ~]# docker rmi 8b43c6af2ad0 Untagged: mysql:5.7 Untagged: mysql@sha256:7a3a7b7a29e6fbff433c339fc52245435fa2c308586481f2f92ab1df239d6a29 # 只删除了5.7 Deleted: sha256:8b43c6af2ad08d95cdcb415d245446909a6cbc1875604c48c4325972e5b00442 Deleted: sha256:aad43f4d2f66438acd2d156216cd544a728851238714975c38d9a690f68afc57 Deleted: sha256:7b9addbc002c1e828aee7ec5c2679b04a591b6fa2b96002701ddee9d4ed54395 Deleted: sha256:b00f8e4e6ce8920fb563615503f232799ab380b338c3f2cbb5e86a2d762a6e80 Deleted: sha256:8fbabb17fd7b46a59cc15301741bf73a527b862f59cc6e84fae15b4dd5c425c0 [root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mysql latest b05128b000dd 11 days ago 516MB hello-world latest feb5d9fea6a5 2 months ago 13.3kB # 删除多个镜像 docker rmi b05128b000dd b05128b000dd # 删除所有镜像 docker rmi $(docker images -aq)
容器命令
有了镜像才可以创建容器,下载一个 centOS 镜像用来测试,即使用docker运行一个linux
-
下载centOS镜像
[root@localhost /]# docker pull centos Using default tag: latest latest: Pulling from library/centos a1d0c7532777: Pull complete Digest: sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177 Status: Downloaded newer image for centos:latest docker.io/library/centos:latest
-
新建运行容器
docker run [可选参数] image # 参数说明 --name="Name" 容器名字 tomcat01、tomcat02,用来区分容器 -d 后台方式运行 -i 以交互模式运行容器,通常与 -t 同时使用 -t 为容器重新分配一个伪输入终端,通常与 -i 同时使用 -p 指定端口映射,格式为:主机(宿主)端口:容器端口 -P 随机端口映射,容器内部端口随机映射到主机的端口
-
启动并进入容器,注意@后的主机,容器内的centos是基础版本,很多命令都是不完善的
[root@localhost /]# docker run -it centos /bin/bash [root@858435a0ad2c /]# ls bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var [root@858435a0ad2c /]#
-
从容器退出
# 停止容器并退出 [root@858435a0ad2c /]# exit exit [root@localhost /]# ls bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var [root@localhost /]# # 不停止容器退出 Ctrl+P+Q [root@8aeea0ae4018 /]# [root@localhost /]# [root@localhost /]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8aeea0ae4018 centos "/bin/bash" 5 minutes ago Up 5 minutes optimistic_brown # 再进入 [root@localhost /]# docker exec -it 8aeea0ae4018 /bin/bash [root@8aeea0ae4018 /]#
-
列出运行的容器
# docker ps # 列出当前正在运行的容器 -a # 列出当前正在运行的容器+带出历史运行过的容器 -n=? # 列出最近创建的n个容器 -q # 静默模式,只显示容器编号 [root@localhost /]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [root@localhost /]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 858435a0ad2c centos "/bin/bash" 5 minutes ago Exited (0) 4 minutes ago compassionate_burnell
-
删除容器
# docker rm docker rm 容器ID # 删除指定的容器,不能删除正在运行的容器,可强制删除:rm -f docker rm -f $(docker ps -aq) # 删除所有的容器 docker ps -a -q | xargs docker rm # 删除所有的容器? [root@localhost /]# docker rm 858435a0ad2c 858435a0ad2c
-
启动停止容器
docker start 容器ID #启动容器 docker restart 容器ID #重启容器 docker stop 容器ID #停止当前运行的容器 docker kill 容器ID #强制停止当前容器
其他常用命令
-
后台启动容器
# docker run -d 镜像名 [root@localhost /]# docker run -d centos [root@localhost /]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES # 问题:docker ps 发现 centos 停止了 # 常见的坑:docker 容器使用后台运行,就必须要有一个前台进程,如 docker run -it centos /bin/bash # docker发现容器没有提供服务,就会自动停止
-
查看日志
# 执行 docker logs -f -t --tail 容器ID,发现没有打印日志 # 自定义一个shell脚本,在centos容器里执行 [root@localhost /]# docker run -d centos /bin/sh -c "while true;do echo helloWorld;sleep 1;done" [root@localhost /]# docker ps CONTAINER ID IMAGE COMMAND ...... 288bdccc178b centos "/bin/sh -c 'while t…" ...... # 显示日志 # -f : 跟踪日志输出 # -t : 显示时间戳 # --tail num :仅列出最新N条容器日志 [root@localhost /]# docker logs -tf --tail 10 288bdccc178b
-
查看容器中进程信息 ps
# top命令 [root@localhost /]# docker top 288bdccc178b UID PID PPID C STIME TTY TIME CMD root 67615 67595 0 22:37 ? 00:00:00 /bin/sh -c while true;do echo helloWorld;sleep 1;done
-
查看容器/镜像元数据
# docker inspect 容器ID [root@localhost /]# docker inspect 288bdccc178b [ { "Id": "288bdccc178bbaf7f1adaa31dd017cc1bf49809fd2b55cc7bef3a930adfcfe97", # 容器ID(完整ID) "Created": "2021-11-30T14:37:43.870138648Z", "Path": "/bin/sh", "Args": [ "-c", "while true;do echo helloWorld;sleep 1;done" # 执行的脚本 ], ... ... } ]
-
进入当前正在运行的容器
# 通常使用后台方式运行,需要进入容器 # 方式一 # 命令:docker exec -it 容器ID bashShell # 测试 [root@localhost /]# docker ps CONTAINER ID IMAGE COMMAND ...... 288bdccc178b centos "/bin/sh -c 'while t…" ...... [root@localhost /]# docker exec -it 288bdccc178b /bin/bash [root@288bdccc178b /]# ps -ef UID PID PPID ... CMD root 1 0 ... /bin/sh -c while true;do echo helloWorld;sleep 1;done root 1573 0 ... /bin/bash root 1598 1 ... /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1 root 1599 1573 ... ps -ef [root@288bdccc178b /]# # 方式二 # docker attach 容器ID # 测试 [root@localhost /]# docker attach 288bdccc178b helloWorld helloWorld helloWorld helloWorld # 停不了,关闭当前终端,重新打开一个终端 [root@localhost /]# docker rm -f $(docker ps -qa) 288bdccc178b eb429d6b97e8 # docker exec # 进入容器后开启一个新的终端(常用) # docker attach # 进入容器正在执行的终端,不会启动新的进程
-
容器与主机之间的数据拷贝
# 常用:容器拷贝到主机 # docker cp 容器ID:容器内路径 目的主机路径 [root@localhost /]# docker ps CONTAINER ID IMAGE COMMAND ...... 28b1861e8c82 centos "/bin/bash" ...... # 进入docker容器,并新建文件,退出 [root@localhost /]# docker attach 28b1861e8c82 [root@28b1861e8c82 /]# cd /home/ [root@28b1861e8c82 home]# ls [root@28b1861e8c82 home]# touch test.java [root@28b1861e8c82 home]# ls test.java [root@28b1861e8c82 home]# exit exit # 容器虽然停止了,但可以将拷贝数据出来 [root@localhost /]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [root@localhost /]# docker ps -a CONTAINER ID IMAGE COMMAND ...... 28b1861e8c82 centos "/bin/bash" ...... [root@localhost /]# docker cp 28b1861e8c82:/home/test.java /home/crater/Desktop/ [root@localhost /]# ll total 0 -rw-r--r--. 1 root root 0 Nov 30 23:30 test.java [root@localhost /]# # 拷贝是一个手动过程,以后使用 -v 卷技术,可以实现自动
小结
可视化面板
目前先使用 portainer,它是一个图形化管理工具,提供一个后台面板供我们操作,后续 CI/CD 阶段再使用 Rancher
-
安装
[root@localhost /]# docker run -d -p 8088:9000 \ --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer Unable to find image 'portainer/portainer:latest' locally latest: Pulling from portainer/portainer 94cfa856b2b1: Pull complete 49d59ee0881a: Pull complete a2300fd28637: Pull complete Digest: sha256:fb45b43738646048a0a0cc74fcee2865b69efde857e710126084ee5de9be0f3f Status: Downloaded newer image for portainer/portainer:latest ffbfef16365ba483d173142cd3491ee950bf07ebd19a600a7028f642a0d519bd [root@localhost tomcat]#
-
访问,新建一个管理员,选择本地连接,可以看到当前的镜像,容器,卷挂载,网络的情况
看看就行,不经常用
实战:Docker 安装 Nginx
-
搜索镜像,建议去dockerHub搜索,可以看到帮助文档
[root@localhost /]# docker search nginx NAME DESCRIPTION STARS OFFICIAL AUTOMATED nginx Official build of Nginx. 15893 [OK] jwilder/nginx-proxy Automated Nginx reverse proxy for docker con… 2098 [OK] ...
-
下载镜像
[root@localhost /]# docker pull nginx Using default tag: latest latest: Pulling from library/nginx eff15d958d66: Pull complete 1e5351450a59: Pull complete 2df63e6ce2be: Pull complete 9171c7ae368c: Pull complete 020f975acd28: Pull complete 266f639b35ad: Pull complete Digest: sha256:097c3a0913d7e3a5b01b6c685a60c03632fc7a2b50bc8e35bcaa3691d788226e Status: Downloaded newer image for nginx:latest docker.io/library/nginx:latest [root@localhost /]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest ea335eea17ab 13 days ago 141MB centos latest 5d0da3dc9764 2 months ago 231MB
-
启动 nginx 容器
[root@localhost /]# docker run -d --name nginx01 -p 18080:80 nginx WARNING: IPv4 forwarding is disabled. Networking will not work. 2d8ac4924b7360618e620db920ce387a26bc9f928c563080f25060d3dae480a4 [root@localhost /]# docker ps CONTAINER ID IMAGE COMMAND ... PORTS NAMES 2d8ac4924b73 nginx "/docker-entrypoint.…" ... 0.0.0.0:18080->80/tcp, :::18080->80/tcp nginx01 [root@localhost /]#
-
测试
# docker run -d --name nginx01 -p 3334:80 nginx # -d 后台运行 # --name 给容器命名 # -p 3334:80 将宿主机的端口18080映射到该容器的80端口 [root@localhost /]# curl localhost:18080 <!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 exec -it nginx01 /bin/bash root@2d8ac4924b73:/# whereis nginx nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx root@2d8ac4924b73:/# cd /etc/nginx/ root@2d8ac4924b73:/etc/nginx#
-
端口暴露
实战:Docker 安装 Tomcat
-
直接运行(run),不需要下载(pull),docker会直接下载
# 官方的教程 # 之前的启动都是后台,停止后容器还是存在,--rm 一般用来测试,用完即删 docker run -it --rm tomcat:9.0 [root@localhost /]# docker run -it --rm tomcat:9.0 Unable to find image 'tomcat:9.0' locally 9.0: Pulling from library/tomcat 5e0b432e8ba9: Pull complete a84cfd68b5ce: Pull complete e8b8f2315954: Pull complete 0598fa43a7e7: Pull complete e0d35e3be804: Pull complete 8fc448a0c88b: Pull complete dbdff6e5955b: Pull complete 5daf3771e3d8: Pull complete 5434ab540d86: Pull complete 80f43f4b2f61: Pull complete Digest: sha256:f80d091e4a086fc1253cdc04011b5cd3c6820e8df5ff3047b0175e105435ba68 Status: Downloaded newer image for tomcat:9.0 Using CATALINA_BASE: /usr/local/tomcat Using CATALINA_HOME: /usr/local/tomcat Using CATALINA_TMPDIR: /usr/local/tomcat/temp Using JRE_HOME: /usr/local/openjdk-11 Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar Using CATALINA_OPTS: NOTE: Picked up JDK_JAVA_OPTIONS: --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED ... 04-Dec-2021 12:39:26.569 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"] ... # Ctrl + c [root@localhost /]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [root@localhost /]# docker ps -a CONTAINER ID IMAGE COMMAND ... 2d8ac4924b73 nginx "/docker-entrypoint.…" ... 28b1861e8c82 centos "/bin/bash" ... [root@localhost /]#
-
不建议–rm,先下载
[root@localhost /]# docker pull tomcat [root@localhost /]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE tomcat 9.0 041804b6c268 23 hours ago 680MB tomcat latest 49842ef82091 23 hours ago 680MB
-
运行,测试
[root@localhost /]# docker run -d -p 28080:8080 --name tomcat01 tomcat # 测试访问 404 # http://虚拟机ip:18080/
-
进入容器:
# 1.Linux命令阉割 # 2.没有webapps,下载的阿里镜像默认是最小镜像,所有不必要的都剔除了,保证最小可运行的环境 [root@localhost /]# docker exec -it tomcat01 /bin/bash root@107a5f9810e2:/usr/local/tomcat# cd webapps root@107a5f9810e2:/usr/local/tomcat/webapps# ls -la total 0 # 页面文件都在webapps.dist目录下 root@107a5f9810e2:/usr/local/tomcat/webapps# cd .. root@107a5f9810e2:/usr/local/tomcat# cd webapps.dist root@107a5f9810e2:/usr/local/tomcat/webapps.dist# ls -al total 4 drwxr-xr-x. 7 root root 81 Nov 9 22:12 . drwxr-xr-x. 1 root root 30 Dec 3 14:18 .. drwxr-xr-x. 3 root root 223 Dec 3 14:17 ROOT drwxr-xr-x. 15 root root 4096 Dec 3 14:17 docs drwxr-xr-x. 7 root root 99 Dec 3 14:17 examples drwxr-xr-x. 6 root root 79 Dec 3 14:17 host-manager drwxr-xr-x. 6 root root 114 Dec 3 14:17 manager # 拷贝到webapps下 -r:递归 root@107a5f9810e2:/usr/local/tomcat/webapps.dist# cd .. root@107a5f9810e2:/usr/local/tomcat# cp -r webapps.dist/* webapps/ root@107a5f9810e2:/usr/local/tomcat# cd webapps root@107a5f9810e2:/usr/local/tomcat/webapps# ls -al total 4 drwxr-xr-x. 1 root root 81 Dec 4 14:13 . drwxr-xr-x. 1 root root 57 Dec 3 14:18 .. drwxr-xr-x. 3 root root 223 Dec 4 14:13 ROOT drwxr-xr-x. 15 root root 4096 Dec 4 14:13 docs drwxr-xr-x. 7 root root 99 Dec 4 14:13 examples drwxr-xr-x. 6 root root 79 Dec 4 14:13 host-manager drwxr-xr-x. 6 root root 114 Dec 4 14:13 manager # 再次访问,加载出Tomcat页面
Docker镜像
镜像是什么
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需要的所有内容,包括代码、运行时、库、环境变量和配置文件。
Docker镜像加载原理
UnionFS(联合文件系统)
Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同的目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union文件系统是Docker镜像的基础。镜像可以通过分层来继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
Docker镜像加载原理
docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统是UnionFS。
bootfs(boot file system)主要包含 bootloader 和 kernel,bootloader 主要是引导加载 kernel,Linux刚启动时会加载 bootfs 文件系统,在 Docker 镜像的最底层是 bootfs。这一层与我们典型的 Linxu/Unix 系统是一样的,包含 boot 加载器和内核。当 boot 加载完成之后整个内核都在内存中了,此时内存的使用权由 bootfs 转交给内核,此时系统也会卸载 bootfs。
rootfs(root file system),在 bootfs 之上。包含的就是典型 Linxu 系统中的 /dev, /proc, /etc 等标准目录和文件。rootfs 就是各种不同操作系统发行版,比如Ubuntu,CentOS 等等。
平时我们安装进虚拟机的CentOS都有好几个G,为什么Docker里才200M?
对于一个精简的OS,rootfs 可以很小,只需要包含最基本的命令、工具和程序库就可以了,因为底层直接用Host的Hernel,自己只需要提供 rootfs 就可以了。由此可见对于不同的 Linux 发行版,bootfs 基本是一致的,rootfs 会有差别,因此不同的发现版本可以公用 bootfs。
分层理解
分层的镜像
下载镜像的时候,从日志输出可以看出来,是一层一层下载
采用分层的结构,最大的好处是资源共享。比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需要在磁盘上保存一份Base镜像,同时内存中也只需要加载一份Base镜像,这样就可以为所有的容器服务,而且镜像的每一层都可以被共享。
查看镜像分层的方式可以通过 docker image inspect
[root@localhost /]# docker image inspect redis:latest
[
{
... ...
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:9321ff862abbe8e1532076e5fdc932371eff562334ac86984a836d77dfb717f5",
"sha256:aa2858ea5edc9c0981901a1b63b49a8f4a6e7099b4304b49e680ffdcc6b71b3e",
"sha256:93079bf13a6d5fe7c4bd9f00cb96183f9d1db9968c4bd15b395df2f3867bf8e5",
"sha256:9ca504b88e256aa6f6c04ec65aeeed6b926661ea30a0b97f829fbe230155241a",
"sha256:9468a3f0498bd5cc298ce25ea6ce9c6adf14aa2ce152856b5f389510a9bb9e01",
"sha256:b7851a62867d82784052d7662862adc0b47b2bddcddc89ae78307f75ba1b29ae"
]
},
... ...
}
]
理解:
所有的 docker 镜像都起始于是个原始镜像,当进行修改或增加新的内容时,就会在当前镜像之上,创建新的镜像。
比如基于Ubuntu 16.04 创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加 Python 包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。
该镜像当前已经包含3个镜像层,如下图所示:
在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含3个文件,而镜像包含了来自两个镜像层的6个文件。
上图中的镜像层跟之前图中的略有区别,主要目的是便于展示文件。
下图中展示了一个稍微复杂的三层镜像,在外部看起来整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版本。
这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新的镜像层添加到镜像中。
Docker 通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像对外展示为统一的文件系统。
Linux 上可用的存储引擎有 AUFS、Overlay2、Device Mapper、Btrfs 以及 ZFS。每种存储引擎都基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都有其独特的特点。
Dcoker在 Windows 上仅支持 windowsfilter 一种存储引擎,改引擎基于 NTFS 文件系统之上实现了分层和CoW
下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。
特点
Docker 镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部。
这一层就是容器层,容器层之下都叫镜像层。
commit镜像
-
commit 命令
# docker commit # 提交容器成为一个新的副本 # 命令和git类似 docker commit -m="提交描述的信息信息" -a="作者" 容器ID 目标镜像名:[TAG]
-
测试
# 1.官方默认的的Tomcat没有webapps应用 # 2.将webapps.dist目录下的文件拷贝到webapps再访问,得到一个可以带有页面的tomcat # 3.使用commit命令将容器提交为一个镜像,之后就可以使用这给修改过的镜像 [root@localhost /]# docker commit -m "带页面的Tomcat" -a "Crater" 107a5f9810e2 tomcat_custom:1.0 sha256:75fd976c5666188c46de812a0a1758adfc701e45dca27cfed80a3a08685351a9 [root@localhost /]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE tomcat_custom 1.0 75fd976c5666 11 seconds ago 684MB tomcat 9.0 041804b6c268 25 hours ago 680MB tomcat latest 49842ef82091 25 hours ago 680MB
容器数据卷
简介
Docker 将应用与运行的环境打包成容器运行,如果不使用docker commit
命令生成新的镜像,那么在容器删除后,Dcoker 容器产生的数据也会被删除,为了可以保存数据,就要在 Dcoker 使用中使用数据卷,将容器内的目录,挂载到宿主 Linux 上。
卷就是目录或文件,存在于一个或多个容器中,由Docker挂载到容器,但卷不属于联合文件系统(Union FileSystem),因此能够绕过联合文件系统提供一些用于持续存储或共享数据的特性。
数据卷的特点:
- 数据卷可在容器之间共享或重用数据
- 卷中的更改可以直接生效
- 数据卷中的更改不会包含在镜像的更新中
- 数据卷的生命周期一直持续到没有容器使用它为止
数据卷的使用(-v)
直接使用命令挂载 -v
# docker run -it -v 主机目录:容器内目录
# 宿主Linux的home目录下只有陨石坑的用户目录
[root@localhost /]# cd /home
[root@localhost home]# ls
crater
# 启动一个centos容器,将容器的home目录挂载到宿主机的/home/test目录
[root@localhost home]# docker run -it -v /home/test:/home centos /bin/bash
[root@3222248f1b85 /]#
# 打开新的会话,看到宿主机上有了test目录
[root@localhost /]# cd /home
[root@localhost home]# ls
crater test
[root@localhost home]#
# 查看容器元数据
[root@localhost home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3222248f1b85 centos "/bin/bash" 15 minutes ago Up 15 minutes condescending_noether
[root@localhost home]# docker inspect 3222248f1b85
[
{
... ...
"Mounts": [ # 挂载
{
"Type": "bind",
"Source": "/home/test", # 宿主机目录
"Destination": "/home", # docker容器内目录
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
... ...
}
]
# 在容器内的home目录下新建文件
[root@3222248f1b85 /]# cd /home
[root@3222248f1b85 home]# touch test.java
[root@3222248f1b85 home]# ls
test.java
# 在宿主机home/test目录下查看
[root@localhost home]# cd test
[root@localhost test]# ls
test.java
# 停止容器(没有客户端使用,退出就停止了)
[root@3222248f1b85 home]# exit
exit
[root@localhost home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# 在宿主机上修改文件,
[root@localhost test]# vim test.java
hello, linux update
~
~
# 再将容器启动并进入,查看修改
[root@localhost home]# docker ps -a
CONTAINER ID IMAGE COMMAND ...
3222248f1b85 centos "/bin/bash" ...
[root@localhost home]# docker start 3222248f1b85
3222248f1b85
[root@localhost home]# docker attach 3222248f1b85
[root@3222248f1b85 /]# cd /home
[root@3222248f1b85 home]# cat test.java
hello, linux update
[root@3222248f1b85 home]#
# 以上可以理解为双向绑定
实战:Docker 安装 MySQL(数据卷)
-
搜索并下载镜像
[root@localhost /]# docker search mysql NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-source relation… 11784 [OK] ... [root@localhost /]# docker pull mysql:5.7 ... [root@localhost home]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mysql 5.7 738e7101490b 2 days ago 448MB
-
在Linux下的MySQL默认的数据文档存储目录为/var/lib/mysql,默认的配置文件的位置/etc/mysql/conf.d,为了确保MySQL镜像或容器删除后,造成的数据丢失,下面建立数据卷保存MySQL的数据和文件。
# 安装启动mysql需要设置密码 -e MYSQL_ROOT_PASSWORD [root@localhost /]# docker run -d \ -p 13306: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 4a6cf19d4702f0b1c6e3a3ffd0c5eda1d0b66e6014efe23bfce07ad6764ce025 [root@localhost /]#
-
用宿主机MySQL客户端连接测试
# 连接测试 [root@localhost /]# mysql -h 127.0.0.1 -P 13306 -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 8 Server version: 5.7.36 MySQL Community Server (GPL) Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> # 数据也同步到宿主机 [root@localhost /]# cd /home/ [root@localhost home]# ls crater mysql test # 之后及时将容器停止删除,挂载到宿主机的数据卷也不会丢失
具名挂载/匿名挂载
-
匿名挂载
匿名挂载就是在指定数据卷的时候,不指定容器路径对应的主机路径,这样对应映射的主机路径就是默认的路径/var/lib/docker/volumes/中自动生成一个随机命名的文件夹。
-
运行并匿名挂载Nginx容器
# -v只写了容器内的路径 # -P: 随机端口映射 [root@localhost /]# docker run -d -P --name nginx01 -v /etc/nginx nginx 94b2dff070383e6d7c47e9423f4e795174cd81ec5984aca960867e3ede6677ba [root@localhost /]# docker volume ls DRIVER VOLUME NAME local 078d4922722ca14400b3bbb3b0f2e3a63ff1c4f9ffc506b56e3cbb656beeffa1
-
具名挂载
具名挂载,就是指定文件夹名称,区别于指定路径挂载,这里的指定文件夹名称是在Docker指定的默认数据卷路径下的。通过
docker volume ls
命令可以查看当前数据卷的目录情况。[root@localhost /]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx a1308fc3305f2dadb41eb03325ae41336623c07cb09c50030f41e8dc507aa2f1 [root@localhost home]# docker volume ls DRIVER VOLUME NAME local 078d4922722ca14400b3bbb3b0f2e3a63ff1c4f9ffc506b56e3cbb656beeffa1 local juming-nginx # 查看指定的数据卷信息 # 命令:docker volume inspect 数据卷名称 [root@localhost /]# docker volume inspect juming-nginx [ { "CreatedAt": "2021-12-05T11:47:17+08:00", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data", "Name": "juming-nginx", "Options": null, "Scope": "local" } ]
-
所有的docker容器的卷,没有指定目录时,都在
/var/lib/docker/volumes/xxx/_data
中[root@localhost /]# cd /var/lib/docker/ [root@localhost docker]# ls buildkit containers image network overlay2 plugins runtimes swarm tmp trust volumes [root@localhost docker]# cd volumes/ [root@localhost volumes]# ll total 24 drwx-----x. 3 root root 19 Dec 5 11:40 078d4922722ca14400b3bbb3b0f2e3a63ff1c4f9ffc506b56e3cbb656beeffa1 brw-------. 1 root root 253, 0 Dec 4 20:32 backingFsBlockDev drwx-----x. 3 root root 19 Dec 5 11:47 juming-nginx -rw-------. 1 root root 32768 Dec 5 11:47 metadata.db [root@localhost volumes]# cd juming-nginx/ [root@localhost juming-nginx]# ls _data [root@localhost juming-nginx]# cd _data/ [root@localhost _data]# ls conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params
-
匿名挂载,具名挂载,指定路径挂载的命令区别如下:
-v 容器内路径 #匿名挂载 -v 卷名:容器内路径 #具名挂载 -v /宿主机路径:容器内路径 #指定路径挂载
-
指定数据卷映射的相关参数:
# ro —— readonly 只读:设置了只读,只能操作宿主机路径内的内容,不能在容器中操作对应的路径。 # rw —— readwrite 可读可写 [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx
数据卷的使用(DockerFile)
初识DockerFile
DockerFile 就是镜像的构建文件,是一个命令脚本。通过脚本可以生成镜像。
-
新建脚本
[root@localhost /]# cd /home [root@localhost home]# mkdir docker-test-volume [root@localhost home]# ls crater docker-test-volume mysql test [root@localhost home]# cd docker-test-volume/ [root@localhost docker-test-volume]# vim dockerfile1 FROM centos VOLUME ["volume01","volume02"] CMD echo "-----end-----" CMD /bin/bash
-
构建镜像
# -f: 指定要使用的Dockerfile路径 # --tag, -t: 镜像的名字及标签 # . : 指定镜像构建过程中的上下文环境的目录,构建的时候,由用户指定构建镜像的上下文路径,而 docker build 会将这个路径下所有的文件都打包上传给 Docker 引擎,引擎内将这些内容展开后,就能获取到所有指定上下文中的文件了。 [root@localhost docker-test-volume]# docker build -f /home/docker-test-volume/dockerfile1 \ -t crater/centos:1.0 . Sending build context to Docker daemon 2.048kB Step 1/4 : FROM centos ---> 5d0da3dc9764 Step 2/4 : VOLUME ["volume01","volume02"] ---> Running in fd40a79d5652 Removing intermediate container fd40a79d5652 ---> 17e35a858d46 Step 3/4 : CMD echo "-----end-----" ---> Running in 5d7c52c41b8f Removing intermediate container 5d7c52c41b8f ---> 44f1e6b80345 Step 4/4 : CMD /bin/bash ---> Running in c1d3d217ca44 Removing intermediate container c1d3d217ca44 ---> 113c2f9874c1 Successfully built 113c2f9874c1 Successfully tagged crater/centos:1.0 [root@localhost docker-test-volume]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE crater/centos 1.0 113c2f9874c1 6 minutes ago 231MB
-
运行测试,启动自己的容器
[root@localhost docker-test-volume]# docker run -it 113c2f9874c1 /bin/bash [root@f753c107fdb6 /]# ls -al total 0 drwxr-xr-x. 1 root root 38 Dec 5 07:03 . drwxr-xr-x. 1 root root 38 Dec 5 07:03 .. -rwxr-xr-x. 1 root root 0 Dec 5 07:03 .dockerenv lrwxrwxrwx. 1 root root 7 Nov 3 2020 bin -> usr/bin drwxr-xr-x. 5 root root 360 Dec 5 07:03 dev drwxr-xr-x. 1 root root 66 Dec 5 07:03 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. 235 root root 0 Dec 5 07:03 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 Dec 4 12:28 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 drwxr-xr-x. 2 root root 6 Dec 5 07:03 volume01 # 这就是生成镜像的时候自动挂载的数据卷 drwxr-xr-x. 2 root root 6 Dec 5 07:03 volume02 [root@f753c107fdb6 /]#
-
这两个卷在宿主机一定有同步的目录,验证一下
[root@f753c107fdb6 /]# cd volume01 [root@f753c107fdb6 volume01]# touch container.txt [root@f753c107fdb6 volume01]# ls container.txt [root@f753c107fdb6 volume01]#
-
打开新的连接,查看容器信息,确认同步成功
[root@localhost /]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f753c107fdb6 113c2f9874c1 "/bin/bash" 3 minutes ago Up 3 minutes reverent_easley [root@localhost /]# docker inspect f753c107fdb6 [ { ... ... "Mounts": [ { "Type": "volume", "Name": "603bec720317ffdbfb9b8842a0129db0baed044776db6daed05cee03af809ab1", "Source": "/var/lib/docker/volumes/603bec720317ffdbfb9b8842a0129db0baed044776db6daed05cee03af809ab1/_data", "Destination": "volume01", # 匿名挂载 "Driver": "local", "Mode": "", "RW": true, "Propagation": "" }, { "Type": "volume", "Name": "eef0a8efe168fc047dc55cbffcc7d52d7040ed654a95a30b72a0484a57f6613a", "Source": "/var/lib/docker/volumes/eef0a8efe168fc047dc55cbffcc7d52d7040ed654a95a30b72a0484a57f6613a/_data", "Destination": "volume02", # 匿名挂载 "Driver": "local", "Mode": "", "RW": true, "Propagation": "" } ], ... ... } ] [root@localhost /]# cd /var/lib/docker/volumes/603bec720317ffdbfb9b8842a0129db0baed044776db6daed05cee03af809ab1/_data/ [root@localhost _data]# ls container.txt
这种方式使用很多,因为通常会自己构建镜像,如果构建镜像时没有挂载卷,在启动时就要手动挂载 -v
数据卷容器
-
启动3个自定义的 centos 容器
-
新的连接运行第2个
-
在 docker01 容器的 volume01 下创建文件,在 docker01 中也可以查询到
docker01:
docker02
-
再启动一个 docker03,进入容器后就可以看到 docker01 创建的文件
-
此时在 docker03 中新建文件,在 docker01 中也可以看到
-
即使停止,删除 docker01,docker02 和 docker03 还是可以访问这个文件,因为它们之间是拷贝的概念
例如:
同步两个MySQL的数据库和配置文件,与上面的操作相同,首先建立数据卷,然后给另一个MySQL容器建立容器数据卷挂载。
[root@localhost home]# docker run -d -p 6603: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
[root@localhost home]# docker run -d -p 6604:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7
【注】
容器之间配置的信息传递,数据卷容器的生命周期一直持续到没有容器使用为止
如果再持久化到宿主机,宿主机的数据不会被删除
DockerFile
Dockerfile是用来构建Docker镜像的文本文件,也可以说是命令参数脚本。docker build
命令用于从Dockerfile构建镜像。可以在docker build
命令中使用 -f
标志指向文件系统中任何位置的Dockerfile。
Docker镜像发布的步骤:
-
编写一个dockerfile文件
-
docker build 构建成为一个镜像
-
docker run 镜像
-
docker push 镜像(发布镜像到DockerHub、阿里云镜像仓库)
在 dockerHub 上,进入 centos 镜像,再进入 gitHub,发现它就是一段命令脚本。
DockerFile构建过程
基础知识
-
每个保留关键字(指令)都是大写字母
-
执行从上到下顺序执行
-
#标识注释
-
每一个指令都会创建提交一个新的镜像层,并提交
dockerFile是面向开发的,通过编写 dockerfile 文件,来交付 docker 镜像,而不再是 jar 包DockerFile:构建文件,定义一切步骤,源代码
DockerImages:通过 DockerFile 构建生成镜像,最终发布和运行
Docker容器:就是镜像运行起来的服务器
DockerFile指令
指令 | 说明 |
---|---|
FROM | 指定基础镜像,一切从这里开始构建 |
MAINTAINER | 镜像是谁写的,姓名+邮箱 |
RUN | 镜像构建的时候需要运行的命令 |
ADD | 将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget |
WORKDIR | 镜像的工作目录 |
VOLUME | 挂载的目录 |
EXPOSE | 保留端口配置 |
CMD | 指定这个容器启动的时候要运行的命令(只有最后一个会生效) |
EMTRYPOINT | 指定这个容器启动的时候要运行的命令,可以追加命令 |
ONBUILD | 当构建一个被继承DockerFile,这个时候就会运行ONBUILD的指令(触发指令) |
COPY | 功能类似ADD,但是是不会自动解压文件,也不能访问网络资源 |
ENV | 构建的时候设置环境变量 |
一个形象的解释各个指令作用的图:
实战:dockerFile 生成镜像
-
新建 dockerFile 文件
# FROM centos:该image文件继承官方的centos,后面加冒号如centos:7,用于指定镜像的版本 # ENV MYPATH /usr/local:设置环境变量MYPATH # WORKDIR $MYPATH:直接使用上面设置的环境变量,指定/usr/local为工作目录 # RUN yum -y install:在/usr/local目录下,安装工具,安装后的依赖和工具都会打包到image文件中 # EXPOSE 80:将容器80端口暴露出来,允许外部连接这个端口 # CMD:指定容器启动的时候运行命令 [root@localhost dockerfile]# pwd /home/dockerfile [root@localhost dockerfile]# cat mydockerfile-centos FROM centos MAINTAINER crater<1813059208@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
-
执行build命令生成image文件,通过docker images来查看新生成的镜像文件。
[root@localhost dockerfile]# docker build -f mydockerfile-centos -t mycentos:1.0 . Sending build context to Docker daemon 2.048kB Step 1/10 : FROM centos ---> 5d0da3dc9764 Step 2/10 : MAINTAINER crater<1813059208@qq.com> ---> Running in b97b56f5bae1 Removing intermediate container b97b56f5bae1 ---> 23803eb3f0d4 Step 3/10 : ENV MYPATH /usr/local ---> Running in 84d02a3b3439 Removing intermediate container 84d02a3b3439 ---> 9cea839951fb Step 4/10 : WORKDIR $MYPATH ---> Running in 1582d30cca1e Removing intermediate container 1582d30cca1e ---> 276cadad6988 Step 5/10 : RUN yum -y install vim ---> Running in ef5139ff16d9 Removing intermediate container ef5139ff16d9 ---> d1cd7b5281ab Step 6/10 : RUN yum -y install net-tools ---> Running in 0767db58cf80 Removing intermediate container 0767db58cf80 ---> 647bb6ddcdbf Step 7/10 : EXPOSE 80 ---> Running in 4a7e3aedbe42 Removing intermediate container 4a7e3aedbe42 ---> 539c29beeaec Step 8/10 : CMD echo $MYPATH ---> Running in c66571fe9bcf Removing intermediate container c66571fe9bcf ---> 1079255f9ace Step 9/10 : CMD echo "---end---" ---> Running in ae26e727b5be Removing intermediate container ae26e727b5be ---> 1fe21e0f06a8 Step 10/10 : CMD /bin/bash ---> Running in 9463dad1a183 Removing intermediate container 9463dad1a183 ---> cc8c205a798d Successfully built cc8c205a798d Successfully tagged mycentos:1.0 [root@localhost dockerfile]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mycentos 1.0 cc8c205a798d About a minute ago 322MB ... ...
-
启动容器
# 启动进入了工作目录/usr/local # 安装的两个工具可以执行 [root@localhost dockerfile]# docker run -it mycentos:1.0 [root@f6d2491fd0fc local]# pwd /usr/local [root@f6d2491fd0fc local]# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255 ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet) RX packets 8 bytes 656 (656.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 [root@f6d2491fd0fc local]# vim [root@f6d2491fd0fc local]#
-
通过
docker history 镜像ID
命令来查看镜像的构建步骤[root@localhost dockerfile]# docker history cc8c205a798d IMAGE CREATED CREATED BY SIZE COMMENT cc8c205a798d 5 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B 1fe21e0f06a8 5 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B 1079255f9ace 5 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B 539c29beeaec 5 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B 647bb6ddcdbf 6 minutes ago /bin/sh -c yum -y install net-tools 27MB d1cd7b5281ab 6 minutes ago /bin/sh -c yum -y install vim 64MB 276cadad6988 6 minutes ago /bin/sh -c #(nop) WORKDIR /usr/local 0B 9cea839951fb 6 minutes ago /bin/sh -c #(nop) ENV MYPATH=/usr/local 0B 23803eb3f0d4 6 minutes ago /bin/sh -c #(nop) MAINTAINER crater<1813059… 0B 5d0da3dc9764 2 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B <missing> 2 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B <missing> 2 months ago /bin/sh -c #(nop) ADD file:805cb5e15fb6e0bb0… 231MB [root@localhost dockerfile]#
RUN、CMD、ENTRYPOINT
-
RUN命令与CMD命令的区别
RUN命令在 image 文件的构建阶段执行,执行结果都会打包进入 image 文件;CMD命令则是在容器启动后执行。
一个 Dockerfile 可以包含多个RUN命令,但是只能有一个CMD命令。
指定了CMD命令以后,docker container run命令就不能附加命令了(比如前面的/bin/bash),否则它会覆盖CMD命令。 -
CMD命令和ENTRYPOINT命令的区别
CMD :指定容器启动的时候要运行的命令,只有最后一个会生效
ENTRYPOINT :指定容器启动的时候要运行的命令,命令可以追加
测试
-
测试 CMD 命令
[root@localhost dockerfile]# cat dockerfile-cmd-test FROM centos CMD ["ls","-a"] [root@localhost dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest:1.0 . Sending build context to Docker daemon 3.072kB Step 1/2 : FROM centos ---> 5d0da3dc9764 Step 2/2 : CMD ["ls","-a"] ---> Running in 43d7ffc32f86 Removing intermediate container 43d7ffc32f86 ---> 9df9cd01732a Successfully built 9df9cd01732a Successfully tagged cmdtest:1.0 [root@localhost dockerfile]# docker run cmdtest:1.0 . .. .dockerenv bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var # 由于使用的是 CMD指令,命令无追加 # -l取代了原本的ls -a,而-l命令不存在所以报错 [root@localhost dockerfile]# docker run cmdtest:1.0 -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. [root@localhost dockerfile]#
-
测试 ENTRYPOINT 命令
[root@localhost dockerfile]# cat dockerfile-entrypoint-test FROM centos ENTRYPOINT ["ls","-a"] [root@localhost dockerfile]# docker build -f dockerfile-entrypoint-test -t cmdtest:2.0 . Sending build context to Docker daemon 4.096kB Step 1/2 : FROM centos ---> 5d0da3dc9764 Step 2/2 : ENTRYPOINT ["ls","-a"] ---> Running in 08abe39ea0bf Removing intermediate container 08abe39ea0bf ---> 95b862a8e4e7 Successfully built 95b862a8e4e7 Successfully tagged cmdtest:2.0 # 运行镜像 [root@localhost dockerfile]# docker run -it cmdtest:2.0 . .dockerenv dev home lib64 media opt root sbin sys usr .. bin etc lib lost+found mnt proc run srv tmp var # 追加命令,再次运行镜像。 [root@localhost dockerfile]# docker run -it cmdtest:2.0 -l total 0 drwxr-xr-x. 1 root root 6 Dec 5 12:39 . drwxr-xr-x. 1 root root 6 Dec 5 12:39 .. -rwxr-xr-x. 1 root root 0 Dec 5 12:39 .dockerenv lrwxrwxrwx. 1 root root 7 Nov 3 2020 bin -> usr/bin drwxr-xr-x. 5 root root 360 Dec 5 12:39 dev drwxr-xr-x. 1 root root 66 Dec 5 12:39 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. 234 root root 0 Dec 5 12:39 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 Dec 4 12:28 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 [root@localhost dockerfile]#
实战:DockerFile 制作 Tomcat 镜像
-
准备镜像文件,tomcat 压缩包,jdk 压缩包
[root@localhost tomcat]# pwd /home/crater/tomcat [root@localhost tomcat]# ll total 153424 -rw-r--r--. 1 root root 11579748 Dec 7 09:20 apache-tomcat-9.0.55.tar.gz -rw-r--r--. 1 root root 145520298 Aug 21 13:08 jdk-8u301-linux-x64.tar.gz [root@localhost tomcat]#
-
编写 Dockerfile,在压缩包所在目录下编写
Dockerfile 是官方文件名,build 命令会自动寻找这个文件
FROM centos MAINTAINER crater<1813059208@qq.com> COPY readme.txt /usr/local/readme.txt ADD jdk-8u301-linux-x64.tar.gz /usr/local ADD apache-tomcat-9.0.55.tar.gz /usr/local RUN yum -y install vim ENV MYPATH /usr/local WORKDIR $MYPATH ENV JAVA_HOME /usr/local/jdk1.8.0_301 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.55 ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.55 ENV PATH $PATH:/$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin EXPOSE 8080 CMD /usr/local/apache-tomcat-9.0.55/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.55/bin/log/catalina.out
-
构建镜像
[root@localhost tomcat]# ll total 153428 -rw-r--r--. 1 root root 11579748 Dec 7 09:20 apache-tomcat-9.0.55.tar.gz -rw-r--r--. 1 root root 635 Dec 7 13:22 Dockerfile -rw-r--r--. 1 root root 145520298 Aug 21 13:08 jdk-8u301-linux-x64.tar.gz -rw-r--r--. 1 root root 0 Dec 7 13:30 readme.txt [root@localhost tomcat]# docker build -t diy_tomcat . Sending build context to Docker daemon 157.1MB Step 1/15 : FROM centos ---> 5d0da3dc9764 Step 2/15 : MAINTAINER crater<1813059208@qq.com> ---> Using cache ---> bcc334ef04e6 Step 3/15 : COPY readme.txt /usr/local/readme.txt ---> 9206ef85b7cb Step 4/15 : ADD jdk-8u301-linux-x64.tar.gz /usr/local ---> a434a1360f2c Step 5/15 : ADD apache-tomcat-9.0.55.tar.gz /usr/local ---> ccc6aa87831e Step 6/15 : RUN yum -y install vim ---> Running in 98baa6280dc2 ... ... Removing intermediate container 98baa6280dc2 ---> 6019082a9e28 Step 7/15 : ENV MYPATH /usr/local ---> Running in ca38b8403256 Removing intermediate container ca38b8403256 ---> 1764e92045a8 Step 8/15 : WORKDIR $MYPATH ---> Running in 71d67d69af5f Removing intermediate container 71d67d69af5f ---> 13d13f72f38a Step 9/15 : ENV JAVA_HOME /usr/local/jdk1.8.0_301 ---> Running in 53798abb3abf Removing intermediate container 53798abb3abf ---> ddecdf93702b Step 10/15 : ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ---> Running in 0182a861f126 Removing intermediate container 0182a861f126 ---> f24d9263027c Step 11/15 : ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.55 ---> Running in 544f68dcd93a Removing intermediate container 544f68dcd93a ---> 51f8f7e953e3 Step 12/15 : ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.55 ---> Running in 97c825f8b8d9 Removing intermediate container 97c825f8b8d9 ---> fcc34a736e24 Step 13/15 : ENV PATH $PATH:/$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin ---> Running in 61041d8d7a6f Removing intermediate container 61041d8d7a6f ---> b86f18843a8a Step 14/15 : EXPOSE 8080 ---> Running in 5de116096fdf Removing intermediate container 5de116096fdf ---> d0fad2c29e37 Step 15/15 : CMD /usr/local/apache-tomcat-9.0.55/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.55/bin/log/catalina.out ---> Running in a83d0b07acf3 Removing intermediate container a83d0b07acf3 ---> 778652bb32ed Successfully built 778652bb32ed Successfully tagged diy_tomcat:latest [root@localhost tomcat]#
-
查看自定义的镜像
[root@localhost tomcat]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE diy_tomcat latest 778652bb32ed 3 minutes ago 673MB ... ...
-
启动自定义镜像,并访问,可以看到 tomcat 初始化页面
[root@localhost /]# docker run -d -p 9090:8080 --name crater_tomcat \ -v /home/crater/tomcat/test:/usr/local/apache-tomcat-9.0.55/webapps/test \ -v /home/crater/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.55/logs diy_tomcat 63789ca30679d843ae3f1e6daca0eff5736f9405d9364f4715ef82fdab795ad4 [root@localhost /]# # 数据卷也成功挂载 [root@localhost tomcat]# pwd /home/crater/tomcat [root@localhost tomcat]# ll total 153428 -rw-r--r--. 1 root root 11579748 Dec 7 09:20 apache-tomcat-9.0.55.tar.gz -rw-r--r--. 1 root root 635 Dec 7 13:22 Dockerfile -rw-r--r--. 1 root root 145520298 Aug 21 13:08 jdk-8u301-linux-x64.tar.gz -rw-r--r--. 1 root root 0 Dec 7 13:30 readme.txt drwxr-xr-x. 2 root root 6 Dec 7 14:26 test # 数据卷 drwxr-xr-x. 2 root root 197 Dec 7 14:26 tomcatlogs # 数据卷 [root@localhost tomcat]#
-
发布一个自己的 web 项目,由于做了卷挂载,直接在宿主机编辑项目就可以发布
test/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> </web-app>
test/index.jsp
<%@ page language="java" contentType="text/html;charset=UTF-8"%> <html> <head> <title>crater index</title> </head> <body> <% out.println("--- hello world ---"); %> </body> </html>
访问
宿主机ip:9090/test
,成功!
发布镜像到 DockerHub
-
在官网 https://hub.docker.com/ 注册账号
-
使用
docker login
命令,登录[root@localhost /]# 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 /]# docker login -u crater18130 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 pull
dockerHub上传镜像的命名规范是
(用户名)/(镜像名):(版本号)
,但是构建镜像时的名称是 diy_tomcat,所以上传之前先用docker tag
命令标记本地镜像# 直接push,拒绝 [root@localhost /]# docker push diy_tomcat Using default tag: latest The push refers to repository [docker.io/library/diy_tomcat] 5dd1286ad677: Preparing 68fa0de95b27: Preparing c0212179b704: Preparing 538263ae5b1b: Preparing 74ddd0ec08fa: Preparing denied: requested access to the resource is denied # 拒绝 # 打标签 [root@localhost tomcat]# docker tag 3ef4c527cca3 crater18130/tomcat:1.0 # 发布成功 [root@localhost tomcat]# docker push crater18130/tomcat:1.0 The push refers to repository [docker.io/crater18130/tomcat] d7bf6a439f9b: Pushed d43e99405529: Pushed 05f42e93b576: Pushed 34563d205909: Pushed 74ddd0ec08fa: Pushed 1.0: digest: sha256:77c8f6ef54d7cedae2c0e4a09d51c1702542c15c2cfc55b4857876cee03affc0 size: 1373
发布镜像到阿里云容器服务
-
登录阿里云容器镜像服务,创建命名空间
-
创建镜像仓库
-
登录阿里云
[root@localhost /]# docker login --username=辛小丰 registry.cn-hangzhou.aliyuncs.com 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 [root@localhost /]#
-
打标签,推送
# 打标签 [root@localhost /]# docker tag 3ef4c527cca3 registry.cn-hangzhou.aliyuncs.com/crater_namespace/crater_repository:1.0 [root@localhost /]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE crater18130/tomcat 1.0 3ef4c527cca3 4 hours ago 673MB diy_tomcat latest 3ef4c527cca3 4 hours ago 673MB registry.cn-hangzhou.aliyuncs.com/crater_namespace/crater_repository 1.0 3ef4c527cca3 4 hours ago 673MB # 推送 [root@localhost /]# docker push registry.cn-hangzhou.aliyuncs.com/crater_namespace/crater_repository:1.0 The push refers to repository [registry.cn-hangzhou.aliyuncs.com/crater_namespace/crater_repository] d7bf6a439f9b: Pushed d43e99405529: Pushed 05f42e93b576: Pushed 34563d205909: Pushed 74ddd0ec08fa: Pushed 1.0: digest: sha256:77c8f6ef54d7cedae2c0e4a09d51c1702542c15c2cfc55b4857876cee03affc0 size: 1373 [root@localhost /]#
以上内容小结
Docker 网络
Docker0 详解
# 清除镜像、容器,干干净净学网络
[root@localhost /]# docker rm -f $(docker ps -aq)
[root@localhost /]# docker rmi -f $(docker images -aq)
查看宿主机的 ip 地址
-
ip addr
只要安装 Docker,就会有一个网卡 docker0,是桥接模式,使用的是 evth-pair 技术。
问题:docker是如何访问网络的
-
启动一个 Tomcat 容器,进入容器查看网络设置
[root@localhost /]# docker run -d -P --name tomcat01 tomcat
容器启动后,Docker 给容器分配了一个
eth0@if49
的网卡如果不能使用
ip addr
命令,需要先进去容器安装一下:apt update && apt install -y iproute2
-
尝试在宿主机 ping 容器,可以 ping 通
-
再次查看宿主机的网络配置信息
可以看到容器内部和Linux主机都会创建一个新的网卡,而这两个网卡都是成对的。使用的技术就是evth-pair。evth-pair 就是一对的虚拟设备接口,他们是成对出现的,一段连着协议,一段彼此相连。evth-pair充当一个桥梁,连接各种虚拟网络设备。
-
再启动一个Tomcat容器,尝试容器之间的网络连接是否能够成功
宿主机和容器查看网络配置信息,又多了一对网卡
-
尝试在tomcat02 容器中 ping tomcat01 容器:
如果 ping 命令不存在,先进入容器执行
apt-get update && apt install iputils-ping
可以看到两个容器是可以连接上的。两个Tomcat容器之间的网络交互模型图如下:
-
说明:
Tomcat01 和 Tomcat02 都使用公用的路由器 docker0。所有的容器不指定网络下,都是由 docker0 路由的,Docker 会给我们容器默认分配一个随机的可用IP地址。
容器网络互联的通用模型,如下图所示:
Docker 中所有的网络接口都是虚拟的,只要容器删除,容器对应的网桥也会删除。
容器互联
在微服务架构中,可以使用 Feign 通过服务名来访问其他微服务,docker也可以用容器名来访问
-
直接 ping 不通
[root@localhost /]# docker ps CONTAINER ID IMAGE COMMAND ... ... NAMES f508ef0a0614 tomcat "catalina.sh run" ... ... tomcat02 899fc7802e11 tomcat "catalina.sh run" ... ... tomcat01 [root@localhost /]# docker exec -it tomcat02 ping tomcat01 ping: tomcat01: Temporary failure in name resolution
-
启动一个 tomcat03 容器使用
--link
连接已经启动的 tomcat02 容器,再用 tomcat03 容器 ping tomcat02,可以 ping 通[root@localhost /]# docker run -d -P --name tomcat03 --link tomcat02 tomcat 043bfed7a6b728895cbda5df6c2adce4290135034a19a510d2cfad440ab9b679 [root@localhost /]# docker exec -it tomcat03 ping tomcat02 PING tomcat02 (172.17.0.3) 56(84) bytes of data. 64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.175 ms 64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.065 ms 64 bytes from tomcat02 (172.17.0.3): icmp_seq=3 ttl=64 time=0.068 ms 64 bytes from tomcat02 (172.17.0.3): icmp_seq=4 ttl=64 time=0.062 ms ^C --- tomcat02 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3000ms rtt min/avg/max/mdev = 0.062/0.092/0.175/0.047 ms [root@localhost /]#
-
但是使用 tomcat02 去 ping tomcat03 ,则还是 ping 不通
[root@localhost /]# docker exec -it tomcat02 ping tomcat03 ping: tomcat03: Temporary failure in name resolution
-
因为
--link
的原理是在 tomcat03 容器中的 /etc/hosts 文件上,添加容器名和ip地址的映射从文件中可以看出,
docker exec -it tomcat03 ping f508ef0a0614
也可以 ping 通[root@localhost /]# docker exec -it tomcat03 cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.3 tomcat02 f508ef0a0614 # 容器名和ip地址的映射 172.17.0.4 043bfed7a6b7
-
tomcat02 容器中并没有添加容器名 tomcat03 和ip地址的映射
[root@localhost /]# docker exec -it tomcat02 cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.3 f508ef0a0614 [root@localhost /]#
目前--link
设置容器互连的方式已经不推荐使用。因为这种方式基于 docker0,而 docker0 不支持容器名访问,所以更多地选择自定义网络
自定义网络 – 容器互联
容器使用自定义网络,就可以实现通过容器名来互相访问。
-
查看 network 相关命令
#帮助命令后显示下面信息 [root@localhost /]# docker network --help Usage: docker network COMMAND Manage networks Options: --help Print usage Commands: connect Connect a container to a network 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. # connect 将某个容器连接到一个docker网络 # create 创建一个docker局域网络 # disconnect 将某个容器退出某个局域网络 # inspect 显示某个局域网络信息 # ls 显示所有docker局域网络 # prune 删除所有未引用的docker局域网络 # rm 删除docker网络
-
显示所有docker局域网络
[root@localhost /]# docker network ls NETWORK ID NAME DRIVER SCOPE 455712685c66 bridge bridge local 67fbf49a4af5 host host local e97fdbcd0447 none null local [root@localhost /]# # bridge: 桥接,docker默认,自定义也使用bridge模式 # none: 不配置网络 # host: 和宿主机共享网络 # container:容器联通,用得少,局限性大
直接启动时,默认使用了参数
--network bridge
docker run -d -P --name tomcat01 docker run -d -P --name tomcat01 --network bridge
自定义网络
-
docker network create
# --driver bridge 桥接模式 # --subnet 192.168.0.0/16 子网,支持 192.168.0.2~192.168.255.254 # --gateway 192.168.0.1 网关 [root@localhost /]# docker network create \ --driver bridge \ --subnet 192.168.0.0/16 \ --gateway 192.168.0.1 \ mynet 02d84cce3c4e0fa73af07fcb9f5d64400a1da8f15af8fcb2847dbf07e6c72f20 [root@localhost /]# docker network ls NETWORK ID NAME DRIVER SCOPE 455712685c66 bridge bridge local 67fbf49a4af5 host host local 02d84cce3c4e mynet bridge local e97fdbcd0447 none null local [root@localhost /]#
-
查看自定义网络信息
[root@localhost /]# docker network inspect mynet [ { "Name": "mynet", "Id": "02d84cce3c4e0fa73af07fcb9f5d64400a1da8f15af8fcb2847dbf07e6c72f20", "Created": "2021-12-06T23:07:37.938428846+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": {} } ]
启动两个容器,指定使用该自定义网络mynet,测试处于自定义网络下的容器,是否可以直接通过容器名进行网络访问
-
启动两个容器,并查看网络信息
[root@localhost /]# docker run -d -P --name tomcat-net-01 --net mynet tomcat:8.0 12f782ea349059cf0242d9454b50a95b33bca1c39a15a0f1c855c81153a205be [root@localhost /]# docker run -d -P --name tomcat-net-02 --net mynet tomcat:8.0 8dadae657abc170c6db2ff5a92275f420b396e493ac9d8452f73b990976d62ad [root@localhost /]# docker network inspect mynet [ { "Name": "mynet", "Id": "02d84cce3c4e0fa73af07fcb9f5d64400a1da8f15af8fcb2847dbf07e6c72f20", "Created": "2021-12-06T23:07:37.938428846+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": { "12f782ea349059cf0242d9454b50a95b33bca1c39a15a0f1c855c81153a205be": { "Name": "tomcat-net-01", "EndpointID": "1dac6b0006f3b19d733d664209054a1e6262e4295b89d654552ea915d18da7e2", "MacAddress": "02:42:c0:a8:00:02", "IPv4Address": "192.168.0.2/16", "IPv6Address": "" }, "8dadae657abc170c6db2ff5a92275f420b396e493ac9d8452f73b990976d62ad": { "Name": "tomcat-net-02", "EndpointID": "0b76911ae8112c99c14521cb90ff015179e43375b709703111024fe721c324db", "MacAddress": "02:42:c0:a8:00:03", "IPv4Address": "192.168.0.3/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ]
-
尝试用 tomcat-net-01 去 ping 一下 tomcat-net-02,
# Ip地址可以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.136 ms 64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.076 ms ^C --- 192.168.0.3 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 2999ms rtt min/avg/max/mdev = 0.061/0.083/0.136/0.032 ms # 容器名称也可以ping通 [root@localhost /]# docker exec -it tomcat-net-01 ping tomcat-net-02 PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data. 64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.056 ms 64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.064 ms ^C --- tomcat-net-02 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 3000ms rtt min/avg/max/mdev = 0.056/0.063/0.069/0.009 ms
自定义的网络默认维护了容器间的网络通信问题,推荐使用自定义实现网络互联。
网络联通
不同网络间的容器是无法进行网络连接的
不同Docker网络之间的容器需要连接的话,需要把作为调用方的容器注册一个ip到被调用方所在的网络上。
-
期望进行如图连接
-
环境准备,并尝试 tomcat-01 连接 mynet 网络下的 tomcat-net-01 容器
[root@localhost /]# docker run -d -P --name tomcat-01 tomcat:8.0 e88b94df9e19eb155054ed1fa3baf8fb2f8b2814119c8b5b67c17ce6221586a1 [root@localhost /]# docker run -d -P --name tomcat-02 tomcat:8.0 cb368feb578e25544c3700fcc3ef1cb98421e131f47ced4de88d4d4369c925f1 [root@localhost /]# docker ps CONTAINER ID IMAGE COMMAND ... ... NAMES cb368feb578e tomcat:8.0 "catalina.sh run" ... ... tomcat-02 e88b94df9e19 tomcat:8.0 "catalina.sh run" ... ... tomcat-01 8dadae657abc tomcat:8.0 "catalina.sh run" ... ... tomcat-net-02 12f782ea3490 tomcat:8.0 "catalina.sh run" ... ... tomcat-net-01 # 尝试连接,失败 [root@localhost /]# docker exec -it tomcat-01 ping tomcat-net-01 ping: unknow host tomcat-net-01
-
容器tomcat-01连接到 mynet 网络上。查看mynet的网络详情,看到 mynet 给容器tomcat-01分配了一个ip地址
一个容器,两个地址
[root@localhost /]# docker network connect mynet tomcat-01 [root@localhost /]# docker network inspect mynet [ { "Name": "mynet", "Id": "02d84cce3c4e0fa73af07fcb9f5d64400a1da8f15af8fcb2847dbf07e6c72f20", "Created": "2021-12-06T23:07:37.938428846+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": { "12f782ea349059cf0242d9454b50a95b33bca1c39a15a0f1c855c81153a205be": { "Name": "tomcat-net-01", "EndpointID": "1dac6b0006f3b19d733d664209054a1e6262e4295b89d654552ea915d18da7e2", "MacAddress": "02:42:c0:a8:00:02", "IPv4Address": "192.168.0.2/16", "IPv6Address": "" }, "8dadae657abc170c6db2ff5a92275f420b396e493ac9d8452f73b990976d62ad": { "Name": "tomcat-net-02", "EndpointID": "0b76911ae8112c99c14521cb90ff015179e43375b709703111024fe721c324db", "MacAddress": "02:42:c0:a8:00:03", "IPv4Address": "192.168.0.3/16", "IPv6Address": "" }, "e88b94df9e19eb155054ed1fa3baf8fb2f8b2814119c8b5b67c17ce6221586a1": { "Name": "tomcat-01", "EndpointID": "960cd6f0169535def51eb8f1371efc950766c54557b28390d61bac4e2f2aa91d", "MacAddress": "02:42:c0:a8:00:04", "IPv4Address": "192.168.0.4/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ] [root@localhost /]#
-
再次并尝试 tomcat-01 连接 mynet 网络下的 tomcat-net-01 容器,成功!
实现不同网络之间的容器互联!
[root@localhost /]# docker exec -it tomcat-01 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.248 ms 64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.063 ms 64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.112 ms 64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=4 ttl=64 time=0.062 ms ^C --- tomcat-net-01 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3000ms rtt min/avg/max/mdev = 0.062/0.121/0.248/0.076 ms [root@localhost /]#
SprinigBoot 微服务打包 Docker 镜像
-
新建一个 SpringBoot 项目,只有一个 controller,Maven打包成 jar 包
package com.example.docker_demo.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * 作者: Crater * 创建时间: 2021/12/8 0:46 */ @RestController public class HelloController { @RequestMapping("/hello") public String hello() { return "hello crater\n"; } }
-
编写 Dockerfile
FROM java:8 COPY *.jar /app.jar CMD ["--server.port=8080"] EXPOSE 8080 ENTRYPOINT ["java","-jar","/app.jar"]
-
上传服务器,生成镜像
[root@localhost idea]# pwd /home/crater/idea [root@localhost idea]# ll total 16340 -rw-r--r--. 1 root root 16727840 Dec 8 00:47 docker_demo-0.0.1-SNAPSHOT.jar -rw-r--r--. 1 root root 114 Dec 8 00:53 Dockerfile [root@localhost idea]# docker build -t demo . Sending build context to Docker daemon 16.73MB Step 1/5 : FROM java:8 8: Pulling from library/java 5040bd298390: Pull complete fce5728aad85: Pull complete 76610ec20bf5: Pull complete 60170fec2151: Pull complete e98f73de8f0d: Pull complete 11f7af24ed9c: Pull complete 49e2d6393f32: Pull complete bb9cdec9c7f3: Pull complete Digest: sha256:c1ff613e8ba25833d2e1940da0940c3824f03f802c449f3d1815a66b7f8c0e9d Status: Downloaded newer image for java:8 ---> d23bdf5b1b1b Step 2/5 : COPY *.jar /app.jar ---> 78d4953d85d7 Step 3/5 : CMD ["--server.port=8080"] ---> Running in ca0d5b9f2d45 Removing intermediate container ca0d5b9f2d45 ---> 0881428042d6 Step 4/5 : EXPOSE 8080 ---> Running in bc1cbe2204a0 Removing intermediate container bc1cbe2204a0 ---> d86cac9cd3ac Step 5/5 : ENTRYPOINT ["java","-jar","/app.jar"] ---> Running in ed4b68a2a83c Removing intermediate container ed4b68a2a83c ---> 7c2d1f4b0356 Successfully built 7c2d1f4b0356 Successfully tagged demo:latest [root@localhost idea]#
-
发布运行
[root@localhost idea]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE demo latest 7c2d1f4b0356 About a minute ago 660MB [root@localhost idea]# docker run -d -p 8080:8080 demo 1e6d18bbd2f1a48c057bc61ff2dca165c2fbff6f7a132719c86354c44380c040 [root@localhost idea]# curl localhost:8080/hello hello crater [root@localhost idea]#