docker容器技术
任务一 安装Docker
1.1 docker简介
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。
容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app)。几乎没有性能开销,可以很容易地在机器和数据中心中运行。最重要的是,他们不依赖于任何语言、框架或包括系统。
1.2 为什么要使用docker
作为一种新兴的虚拟化方式,Docker 跟传统的虚拟化方式相比具有众多的优势。
首先,Docker 容器的启动可以在秒级实现,这相比传统的虚拟机方式要快得多。 其次,Docker 对系统资源的利用率很高,一台主机上可以同时运行数千个 Docker 容器。
容器除了运行其中应用外,基本不消耗额外的系统资源,使得应用的性能很高,同时系统的开销尽量小。传统虚拟机方式运行 10 个不同的应用就要起 10 个虚拟机,而Docker 只需要启动 10 个隔离的应用即可。
Docker主要解决的问题:
保证程序运行环境的一致性;
降低配置开发环境、生产环境的复杂度及成本;
实现程序的快速部署和分发。
1.3 Docker安装
(1)环境准备
在centos7机器上关闭防火墙和SELinux。
关闭firewalld
[root@docker ~]# systemctl stop firewalld [root@docker ~]# systemctl disable firewalld
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
Removed symlink /etc/systemd/system/basic.target.wants/firewalld.service.
关闭selinux
[root@docker ~]# setenforce 0 [root@docker ~]# sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
(2)安装Docker
安装必要的依赖包。
[root@docker ~]# yum -y install yum-utils device-mapper-persistent-data lvm2
添加软件源信息。
[root@docker ~]# yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo Loaded plugins: fastestmirror adding repo from: http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo grabbing file http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo to /etc/yum.repos.d/docker-ce.repo repo saved to /etc/yum.repos.d/docker-ce.repo
更新并安装 Docker-CE。
[root@docker ~]# yum makecache fast Loaded plugins: fastestmirror base | 3.6 kB 00:00 docker-ce-stable | 3.5 kB 00:00 extras | 2.9 kB 00:00 updates | 2.9 kB 00:00 (1/2): docker-ce-stable/7/x86_64/updateinfo | 55 B 00:00 (2/2): docker-ce-stable/7/x86_64/primary_db | 62 kB 00:00 Loading mirror speeds from cached hostfile * base: mirrors.aliyun.com * extras: mirrors.aliyun.com * updates: mirrors.aliyun.com Metadata Cache Created [root@docker ~]# yum -y install docker-ce
开启docker服务。
[root@docker ~]# systemctl daemon-reload [root@docker ~]# systemctl restart docker [root@docker ~]# systemctl enable docker Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
任务二 Docker镜像管理/仓库管理
2.1 什么是镜像
简单说, Docker镜像是一个不包含Linux内核而又精简的Linux操作系统。
2.2 镜像从哪里来
Docker Hub是由Docker公司负责维护的公共注册中心,包含大量的容器镜像, Docker工具默认从这个公共镜像库下载镜像。
https://hub.docker.com/explore
默认是国外的源,下载会慢,可以国内的源提供下载速度:
curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://04be47cf.m.daocloud.io
2.3 镜像的基本操作
选项 |
描述 |
ls |
列出镜像 |
build |
构建镜像来自Dockerfile |
history |
查看镜像历史 |
inspect |
显示一个或多个镜像详细信息 |
pull |
发布容器端口到主机 |
push |
推送一个镜像到镜像仓库 |
prune |
移除未使用的镜像。没有被标记或被任何容器引用的。 |
export |
将文件系统作为一个tar归档文件导出到STDOUT |
import |
从归档文件中创建镜像 |
tag |
连接容器到一个网络 |
load |
将镜像存储文件导入到本地镜像库 |
-v |
绑定挂载一个卷 |
--restart |
容器退出时重启策略,默认no |
2.4 注册仓库DockerHub
https://hub.docker.com/ 注册账号,登录邮箱激活
登录dockerhub
[root@docker ~]# docker login docker.io Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. Username: jyy11 #输入注册的用户名 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
2.5 搜索镜像
搜索alpine、nginx镜像
[root@docker ~]# docker search alpine NAME DESCRIPTION STARS OFFICIAL AUTOMATED alpine A minimal Docker image based on Alpine Linux… 7605 [OK] mhart/alpine-node Minimal Node.js built on Alpine Linux 483 anapsix/alpine-java Oracle Java 8 (and 7) with GLIBC 2.28 over A… 470 [OK] frolvlad/alpine-glibc Alpine Docker image with glibc (~12MB) 261 [OK] alpine/git A simple git container running in alpine li… 184 [OK] mvertes/alpine-mongo light MongoDB container 116 [OK] yobasystems/alpine-mariadb MariaDB running on Alpine Linux [docker] [am… 91 [OK] alpine/socat Run socat command in alpine container 69 [OK] kiasaki/alpine-postgres PostgreSQL docker image based on Alpine Linux 44 [OK] jfloff/alpine-python A small, more complete, Python Docker image … 41 [OK] zzrot/alpine-caddy Caddy Server Docker Container running on Alp… 35 [OK] zenika/alpine-chrome Chrome running in headless mode in a tiny Al… 34 [OK] byrnedo/alpine-curl Alpine linux with curl installed and set as … 34 [OK] hermsi/alpine-sshd Dockerize your OpenSSH-server with rsync and… 33 [OK] hermsi/alpine-fpm-php FPM-PHP 7.0 to 8.0, shipped along with tons … 25 [OK] etopian/alpine-php-wordpress Alpine WordPress Nginx PHP-FPM WP-CLI 25 [OK] bashell/alpine-bash Alpine Linux with /bin/bash as a default she… 18 [OK] roribio16/alpine-sqs Dockerized ElasticMQ server + web UI over Al… 14 [OK] davidcaste/alpine-java-unlimited-jce Oracle Java 8 (and 7) with GLIBC 2.21 over A… 13 [OK] spotify/alpine Alpine image with `bash` and `curl`. 11 [OK] cfmanteiga/alpine-bash-curl-jq Docker Alpine image with Bash, curl and jq p… 6 [OK] apteno/alpine-jq Weekly build of alpine image with curl, wget… 1 ellerbrock/alpine-mysql-client MySQL Client based on Alpine Linux 1 [OK] dwdraju/alpine-curl-jq Alpine Docker Image with curl, jq, bash 1 [OK] bushrangers/alpine-caddy Alpine Linux Docker Container running Caddys… 1 [OK]
[root@docker ~]# docker search nginx NAME DESCRIPTION STARS OFFICIAL AUTOMATED nginx Official build of Nginx. 15093 [OK] jwilder/nginx-proxy Automated Nginx reverse proxy for docker con… 2037 [OK] richarvey/nginx-php-fpm Container running Nginx + PHP-FPM capable of… 816 [OK] jc21/nginx-proxy-manager Docker container for managing Nginx proxy ho… 205 linuxserver/nginx An Nginx container, brought to you by LinuxS… 147 tiangolo/nginx-rtmp Docker image with Nginx using the nginx-rtmp… 131 [OK] jlesage/nginx-proxy-manager Docker container for Nginx Proxy Manager 119 [OK] alfg/nginx-rtmp NGINX, nginx-rtmp-module and FFmpeg from sou… 101 [OK] bitnami/nginx Bitnami nginx Docker Image 98 [OK] nginxdemos/hello NGINX webserver that serves a simple page co… 70 [OK] privatebin/nginx-fpm-alpine PrivateBin running on an Nginx, php-fpm & Al… 56 [OK] nginx/nginx-ingress NGINX and NGINX Plus Ingress Controllers fo… 55 nginxinc/nginx-unprivileged Unprivileged NGINX Dockerfiles 40 staticfloat/nginx-certbot Opinionated setup for automatic TLS certs lo… 23 [OK] nginx/nginx-prometheus-exporter NGINX Prometheus Exporter for NGINX and NGIN… 19 schmunk42/nginx-redirect A very simple container to redirect HTTP tra… 19 [OK] centos/nginx-112-centos7 Platform for running nginx 1.12 or building … 15 centos/nginx-18-centos7 Platform for running nginx 1.8 or building n… 13 flashspys/nginx-static Super Lightweight Nginx Image 10 [OK] bitnami/nginx-ingress-controller Bitnami Docker Image for NGINX Ingress Contr… 9 [OK] mailu/nginx Mailu nginx frontend 8 [OK] devilbox/nginx-stable Devilbox's Nginx stable (based on official N… 4 ansibleplaybookbundle/nginx-apb An APB to deploy NGINX 2 [OK] wodby/nginx Generic nginx 1 [OK] centos/nginx-110-centos7 Platform for running nginx 1.10 or building … 0
2.6 下载镜像
下载alpine镜像
[root@docker ~]# docker pull alpine Using default tag: latest latest: Pulling from library/alpine 5843afab3874: Pull complete Digest: sha256:234cb88d3020898631af0ccbbcca9a66ae7306ecd30c9720690858c1b007d2a0 Status: Downloaded newer image for alpine:latest docker.io/library/alpine:latest
下载nginx镜像
[root@docker ~]# docker pull nginx Using default tag: latest latest: Pulling from library/nginx b4d181a07f80: Pull complete edb81c9bc1f5: Pull complete b21fed559b9f: Pull complete 03e6a2452751: Pull complete b82f7f888feb: Pull complete 5430e98eba64: Pull complete Digest: sha256:47ae43cdfc7064d28800bc42e79a429540c7c80168e8c8952778c0d5af1c09db Status: Downloaded newer image for nginx:latest docker.io/library/nginx:latest
下载指定tag
[root@docker ~]# docker pull alpine:3.12.3 3.12.3: Pulling from library/alpine 801bfaa63ef2: Pull complete Digest: sha256:3c7497bf0c7af93428242d6176e8f7905f2201d8fc5861f45be7a346b5f23436 Status: Downloaded newer image for alpine:3.12.3 docker.io/library/alpine:3.12.3
2.7 查看本地镜像
[root@docker ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 4f380adfc10f 8 days ago 133MB alpine latest d4ff818577bc 2 weeks ago 5.59MB alpine 3.12.3 389fef711851 6 months ago 5.57MB
2.8 给镜像打标签
[root@docker ~]# docker tag 389fef711851 docker.io/jyy11/alpine:v3.12.3 [root@docker ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 4f380adfc10f 8 days ago 133MB alpine latest d4ff818577bc 2 weeks ago 5.59MB jyy11/alpine v3.12.3 389fef711851 6 months ago 5.57MB alpine 3.12.3 389fef711851 6 months ago 5.57MB
2.9 推送镜像
[root@docker ~]# docker push docker.io/jyy11/alpine:v3.12.3 The push refers to repository [docker.io/jyy11/alpine] 777b2c648970: Layer already exists v3.12.3: digest: sha256:074d3636ebda6dd446d0d00304c4454f468237fdacf08fb0eeac90bdbfa1bac7 size: 528
2.10 删除镜像
[root@docker ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 4f380adfc10f 8 days ago 133MB alpine latest d4ff818577bc 2 weeks ago 5.59MB jyy11/alpine v3.12.3 389fef711851 6 months ago 5.57MB alpine 3.12.3 389fef711851 6 months ago 5.57MB [root@docker ~]# docker rmi -f 389fef711851 Untagged: jyy11/alpine:v3.12.3 Untagged: jyy11/alpine@sha256:074d3636ebda6dd446d0d00304c4454f468237fdacf08fb0eeac90bdbfa1bac7 Untagged: alpine:3.12.3 Untagged: alpine@sha256:3c7497bf0c7af93428242d6176e8f7905f2201d8fc5861f45be7a346b5f23436 Deleted: sha256:389fef7118515c70fd6c0e0d50bb75669942ea722ccb976507d7b087e54d5a23 Deleted: sha256:777b2c648970480f50f5b4d0af8f9a8ea798eea43dbcf40ce4a8c7118736bdcf [root@docker ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 4f380adfc10f 8 days ago 133MB alpine latest d4ff818577bc 2 weeks ago 5.59MB
任务三 通过容器创建镜像
3.1 通过镜像启动容器
(1)查看镜像
[root@docker ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 4f380adfc10f 8 days ago 133MB alpine latest d4ff818577bc 2 weeks ago 5.59MB
(2)根据镜像启动容器
[root@docker ~]# docker run -ti --name nginx -d nginx 05b6d53eba208459f35f80fae631581c438ef719b7c3a7063a5ea6f24f8dfd5d [root@docker ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 05b6d53eba20 nginx "/docker-entrypoint.…" 14 seconds ago Up 13 seconds 80/tcp nginx
3.2 根据启动的容器创建新的镜像
[root@docker ~]# docker commit -a "cool" -m "this is test" 05b6d53eba20 nginx:1.0 sha256:a4ffdca819c98423d75d0d4e7adfc017f16b89a4272f8cdbea77f575c2a4e30d [root@docker ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx 1.0 a4ffdca819c9 9 seconds ago 133MB nginx latest 4f380adfc10f 8 days ago 133MB alpine latest d4ff818577bc 2 weeks ago 5.59MB
docker commit : 从容器创建一个新的镜像
-a:提交的镜像作者;
-c:使用Dockerfile指令来创建镜像;
-m:提交时的说明文字;
-p:在commit时,将容器暂停。
任务四 Docker容器管理
4.1 容器管理
选项 |
描述 |
-i |
交互式 |
-t |
分配一个为终端 |
-d |
运行容器到后台 |
-e |
设置环境变量 |
-p |
发布容器端口到主机 |
-P |
发布容器所有EXPOSE的端口到宿主机随机端口 |
--name |
指定容器名称 |
-h |
指定容器主机名 |
--ip |
指定容器IP,只能用于自定义网络 |
--network |
连接容器到一个网络 |
--mount |
将文件系统附加到容器 |
-v |
绑定挂载一个卷 |
--restart |
容器退出时重启策略,默认no |
(1)运行容器
[root@docker ~]# docker run -dti --name nginx1.0 -p 80:80 nginx 0abee55b945210266d3391119901e54c641f38932d6c2647fed117989c66861c [root@docker ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0abee55b9452 nginx "/docker-entrypoint.…" 5 seconds ago Up 4 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp nginx1.0 05b6d53eba20 nginx "/docker-entrypoint.…" 4 minutes ago Up 4 minutes 80/tcp nginx
docker run : 从容器创建一个新的镜像
-i:交互式操作;
-t:终端;
-d:容器在后台运行;
-p:端口映射;
--name:为容器指定一个名称;
指明了-d运行镜像,会返回容器id;如果不指明-d运行镜像,会打印出catalina.out的日志,在[crtl+c]后,容器即停止运行。
(2)终止容器
[root@docker ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0abee55b9452 nginx "/docker-entrypoint.…" 5 seconds ago Up 4 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp nginx1.0 05b6d53eba20 nginx "/docker-entrypoint.…" 4 minutes ago Up 4 minutes 80/tcp nginx [root@docker ~]# docker stop 0abee55b9452 05b6d53eba20 0abee55b9452 05b6d53eba20 [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 0abee55b9452 nginx "/docker-entrypoint.…" About a minute ago Exited (0) 31 seconds ago nginx1.0 05b6d53eba20 nginx "/docker-entrypoint.…" 6 minutes ago Exited (0) 31 seconds ago nginx
(3)启动容器
[root@docker ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0abee55b9452 nginx "/docker-entrypoint.…" About a minute ago Exited (0) 31 seconds ago nginx1.0 05b6d53eba20 nginx "/docker-entrypoint.…" 6 minutes ago Exited (0) 31 seconds ago nginx [root@docker ~]# docker start 0abee55b9452 0abee55b9452 [root@docker ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0abee55b9452 nginx "/docker-entrypoint.…" 3 minutes ago Up 5 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp nginx1.0
docker container start [CONTAINER ID] 启动容器
docker container stop [CONTAINER ID] 终止容器
docker start $(docker ps -aq) --备注:启动所有 docker 容器
(4)进入/退出容器
docker exec -it [CONTAINER ID] bash 进入容器
[root@docker ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0abee55b9452 nginx "/docker-entrypoint.…" 3 minutes ago Up 5 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp nginx1.0 [root@docker ~]# docker exec -it 0abee55b9452 /bin/sh # ls bin docker-entrypoint.d home media proc sbin tmp boot docker-entrypoint.sh lib mnt root srv usr dev etc lib64 opt run sys var # exit 退出容器
(5)容器导出和导入
容器导出
#这样将导出容器快照到本地文件
docker export [CONTAINER ID] > [tar file]
[root@docker ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0abee55b9452 nginx "/docker-entrypoint.…" 7 minutes ago Up 4 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp nginx1.0 [root@docker ~]# docker export 0abee55b9452 > nginx1.0.tar [root@docker ~]# ls anaconda-ks.cfg nginx1.0.tar
容器导入
#从容器快照文件中再导入为镜像
cat [tar file] | docker import - [name:tag]
[root@docker ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx 1.0 a4ffdca819c9 13 minutes ago 133MB nginx latest 4f380adfc10f 8 days ago 133MB alpine latest d4ff818577bc 2 weeks ago 5.59MB [root@docker ~]# cat nginx1.0.tar | docker import - nginx1.0.1 sha256:d0d786bb421210aaae81f14cf4f84fc6de4ae21d5a23fda04a6daeaac25b5b1f [root@docker ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx1.0.1 latest d0d786bb4212 6 seconds ago 131MB nginx 1.0 a4ffdca819c9 14 minutes ago 133MB nginx latest 4f380adfc10f 8 days ago 133MB alpine latest d4ff818577bc 2 weeks ago 5.59MB
(6)删除容器
#删除终止状态的容器
docker rm [CONTAINER ID]
#删除所有处于终止状态的容器
docker container prune
#删除运行中的容器
docker rm -f [CONTAINER ID]
[root@docker ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0abee55b9452 nginx "/docker-entrypoint.…" 14 minutes ago Up 11 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp nginx1.0 [root@docker ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0abee55b9452 nginx "/docker-entrypoint.…" 15 minutes ago Up 12 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp nginx1.0 05b6d53eba20 nginx "/docker-entrypoint.…" 19 minutes ago Exited (0) 13 minutes ago nginx [root@docker ~]# docker rm 05b6d53eba20 05b6d53eba20 [root@docker ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0abee55b9452 nginx "/docker-entrypoint.…" 16 minutes ago Up 13 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp nginx1.0 [root@docker ~]# docker rm -f 0abee55b9452 0abee55b9452 [root@docker ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
任务五 Docker数据管理
生产环境使用Docker的过程中,往往需要对数据进行持久化保存,或者需要更多容器之间进行数据共享,那我们需要怎么操作呢?
答案就是:数据卷(Data Volumes)和数据卷容器(Data Volume Contain)
5.1 数据卷
(1)数据卷简介
数据卷就是将宿主机的某个目录,映射到容器中,作为数据存储的目录,我们就可以在宿主机对数据进行存储。
数据卷(Data Volumes):容器内数据映射到本地主机环境。
1.数据卷可以在容器之间共享和重用,本地与容器间传递数据更搞笑;
2.对数据卷的修改会立马有效,容器内部与本地目录均可;
3.对数据卷的更新,不会影响镜像,对数据与应用进行了解耦操作;
4.数据卷默认会一直存在,即使容器被删除。
(2)数据卷实践
命令格式:
docker run -dti --name [容器名字] -v [宿主机目录]:[容器目录] [镜像名称] [命令(可选)]
[root@docker ~]# mkdir /data #创建目录 [root@docker ~]# echo "test" > /data/test.txt #创建一个test文件 [root@docker ~]# docker run -dti --name test1 -v /data/:/data/ nginx #启动一个容器,挂载数据卷 6238fce7a44ec0c3aecd8c51b44bac98b4cf98ca6c4eec92db7fd637bc2d18a5 [root@docker ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6238fce7a44e nginx "/docker-entrypoint.…" 11 seconds ago Up 11 seconds 80/tcp test1 [root@docker ~]# docker exec -it 6238fce7a44e /bin/bash root@6238fce7a44e:/# cat /data/test.txt test
注意:
1、Docker挂载数据卷的默认读写权限(rw),用户可以通过ro设置为只读,格式:[宿主机文件]:[容器文件]:ro
2、如果直接挂载一个文件到容器,使用文件工具进行编辑,可能会造成文件的改变,从Docker1.1.0起,这会导致报错误信息。所以推荐的方式是直接挂载文件所在的目录。
5.2 数据卷容器
(1)数据卷容器简介
数据卷容器需要再多个容器之间共享一些持续更新的数据,最简单的方式是使用数据卷容器。数据卷容器也是一个容器,但是它的目的是专门用来提供数据卷供其他容器挂载。
数据卷容器(Data Volume Containers):使用特定容器维护数据卷。
简单点:数据卷容器就是为其他容器提供数据交互存储的容器。
(2)数据卷容器实践
命令格式:
Docker run --help
-v,--volumes-from list
数据卷容器操作流程:
如果使用数据卷容器,在多个容器间共享数据,并永久保存这些数据,需要有一个规范的流程才能做的到:
1、创卷数据卷容器
2、其他容器挂载数据卷容器
注意:数据卷容器自身并不需要启动,但是启动的时候仍然可以进行数据卷容器的工作。
创建一个数据卷容器
命令格式:
docker create -v [容器数据卷目录] --name [容器名字] [镜像名称]
执行效果:
[root@docker ~]# docker create -v /data1 --name v-data1 nginx c0a4afb5172e9876889b27317826d5f0a77350021bc57e12fe27339f8569cbd0 [root@docker ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c0a4afb5172e nginx "/docker-entrypoint.…" 6 seconds ago Created v-data1 6238fce7a44e nginx "/docker-entrypoint.…" 3 minutes ago Up 3 minutes 80/tcp test1
创建两个容器,同时挂载数据卷容器
docker run --volumes-from [数据卷容器id/name] -dti --name [容器名字] [镜像名称] [命令(可选)]
创建v01容器:
[root@docker ~]# docker run --volumes-from v-data1 -dti --name v01 nginx 6656742755ef44b73315dc8e0d037a43a9a84a11cca3068e3654f3ad855fac17
创建v02容器
[root@docker ~]# docker run --volumes-from v-data1 -dti --name v02 nginx f8fec47eeb6f792f1f55444161438f4204efd269aaf563026f31865b7637fd04
[root@docker ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f8fec47eeb6f nginx "/docker-entrypoint.…" 10 seconds ago Up 9 seconds 80/tcp v02 6656742755ef nginx "/docker-entrypoint.…" 25 seconds ago Up 24 seconds 80/tcp v01 c0a4afb5172e nginx "/docker-entrypoint.…" 2 minutes ago Created v-data1
确认卷容器共享
进入v01,操作数据卷容器:
[root@docker ~]# docker exec -it 6656742755ef /bin/bash root@6656742755ef:/# ls /data1/ root@6656742755ef:/# echo 'v01'>/data1/v01.txt root@6656742755ef:/# exit exit
进入v02,确认数据卷:
[root@docker ~]# docker exec -it f8fec47eeb6f /bin/bash root@f8fec47eeb6f:/# echo 'v02'>/data1/v02.txt root@f8fec47eeb6f:/# ls /data1/ v01.txt v02.txt root@f8fec47eeb6f:/# exit exit
任务六 Docker网络管理
6.1 网络模式
(1)bridge模式
当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。
从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。
bridge模式是docker的默认网络模式,不写--net参数,就是bridge模式。使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看。
创建一个bridge网络的容器
[root@docker ~]# docker run -it busybox Unable to find image 'busybox:latest' locally latest: Pulling from library/busybox b71f96345d44: Pull complete Digest: sha256:930490f97e5b921535c153e0e7110d251134cc4b72bbb8133c6a5065cc68580d Status: Downloaded newer image for busybox:latest / #
(2)host模式
如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就不能再用了,网络的隔离性不好。
创建一个host网络的容器
[root@docker ~]# docker run -it --network host busybox / # ifconfig docker0 Link encap:Ethernet HWaddr 02:42:1D:55:63:5A inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0 inet6 addr: fe80::42:1dff:fe55:635a/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:7 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:522 (522.0 B) eno16777736 Link encap:Ethernet HWaddr 00:0C:29:6D:82:5C inet addr:192.168.174.29 Bcast:192.168.174.255 Mask:255.255.255.0 inet6 addr: fe80::20c:29ff:fe6d:825c/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:175298 errors:0 dropped:0 overruns:0 frame:0 TX packets:68165 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:228499782 (217.9 MiB) TX bytes:4557382 (4.3 MiB) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:4 errors:0 dropped:0 overruns:0 frame:0 TX packets:4 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:348 (348.0 B) TX bytes:348 (348.0 B) veth21cfacc Link encap:Ethernet HWaddr 5E:EC:48:A1:B5:84 inet6 addr: fe80::5cec:48ff:fea1:b584/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:648 (648.0 B) vethc60f0b0 Link encap:Ethernet HWaddr 7A:B8:9E:A2:FF:0C inet6 addr: fe80::78b8:9eff:fea2:ff0c/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:648 (648.0 B) vethc78b7e3 Link encap:Ethernet HWaddr 7A:0C:AE:A6:48:19 inet6 addr: fe80::780c:aeff:fea6:4819/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:648 (648.0 B) / #
通过以上实验得知,该容器的网络与宿主机一样,直接使用Docker host的网络,最大的好处就是性能,如果容器对网络传输效率有较高要求,则可以选择host网络。当然不变之处就是牺牲一些灵活性,比如要考虑端口冲突风问题,Docker host上已经使用的端口就不能再用了。
(3)none模式
使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。
这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过--network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。
创建一个none网络的容器
[root@docker ~]# docker run -it --network none busybox / # ifconfig lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) / #
比如某个容器的唯一用途是生产随机密码,就可以放到none网络中避免密码被窃取。
(4)自定义网络模式
创建my_net网络,系统默认IP地址段自动向后递增
[root@docker ~]# docker network create --driver bridge my_net a99ec50f9db520b7c1d7c7eeca16a11ec17671e0780b8ce31fb60c7f4bfe167e [root@docker ~]# ifconfig br-a99ec50f9db5: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.18.0.1 netmask 255.255.0.0 broadcast 172.18.255.255 inet6 fe80::42:b8ff:fe2d:975 prefixlen 64 scopeid 0x20<link> ether 02:42:b8:2d:09:75 txqueuelen 0 (Ethernet) RX packets 4 bytes 348 (348.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 4 bytes 348 (348.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255 inet6 fe80::42:1dff:fe55:635a prefixlen 64 scopeid 0x20<link> ether 02:42:1d:55:63:5a txqueuelen 0 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 7 bytes 522 (522.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 eno16777736: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.174.29 netmask 255.255.255.0 broadcast 192.168.174.255 inet6 fe80::20c:29ff:fe6d:825c prefixlen 64 scopeid 0x20<link> ether 00:0c:29:6d:82:5c txqueuelen 1000 (Ethernet) RX packets 175897 bytes 228855149 (218.2 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 68479 bytes 4592725 (4.3 MiB) 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 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 0 (Local Loopback) RX packets 4 bytes 348 (348.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 4 bytes 348 (348.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 veth21cfacc: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet6 fe80::5cec:48ff:fea1:b584 prefixlen 64 scopeid 0x20<link> ether 5e:ec:48:a1:b5:84 txqueuelen 0 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 8 bytes 648 (648.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 vethc60f0b0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet6 fe80::78b8:9eff:fea2:ff0c prefixlen 64 scopeid 0x20<link> ether 7a:b8:9e:a2:ff:0c txqueuelen 0 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 8 bytes 648 (648.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 vethc78b7e3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet6 fe80::780c:aeff:fea6:4819 prefixlen 64 scopeid 0x20<link> ether 7a:0c:ae:a6:48:19 txqueuelen 0 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 8 bytes 648 (648.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
使用自定义网络创建容器
[root@docker ~]# docker run --network my_net -it busybox / # ifconfig eth0 Link encap:Ethernet HWaddr 02:42:AC:12:00:02 inet addr:172.18.0.2 Bcast:172.18.255.255 Mask:255.255.0.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:6 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:508 (508.0 B) TX bytes:0 (0.0 B) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) / #
任务七 Dockerfile使用
7.1 Dockerfile介绍
Dockerfile 是用来构建 Docker 镜像的构建文件,是由一系列命令和参数构成的脚本。
1.基础知识
每条保留字指令都必须为大写字母且后面要跟随至少一个参数
指令按照从上到下,顺序执行
# 表示注释
每条指令都会创建一个新的镜像层,并对镜像进行提交
2.Docker 执行 DockerFile 的大致流程
docker 从基础镜像运行一个容器
执行一条指令并对容器作出修改
执行类似 docker commit 的操作提交一个新的镜像层
docker 再基于刚提交的镜像运行一个新容器
执行 dockerfile 中的下一条指令直到所有指令都执行完成
7.2 Dockerfile指令
指令 |
描述 |
FROM |
构建新镜像是基于哪个镜像 |
MAINTAINER |
镜像维护者姓名或邮箱地址 |
RUN |
构建镜像时运行的shell命令 |
COPY |
拷贝文件或目录到镜像中 |
ENV |
设置环境变量 |
USER |
为RUN、CMD、ENTRYPOINT执行命令指定运行用户 |
EXPOSE |
声明容器运行的服务端口 |
HEALTHCHECK |
容器中服务健康检查 |
WORKDIR |
为RUN、CMD、ENTRYPOINT、COPY和ADD设置工作目录 |
ENTRYPOINT |
运行容器时,如果有多个ENTRYPOINT指令,最后一个生效 |
CMD |
运行容器时执行,如果有多个CMD指令,最后一个生效 |
7.3 自定义镜像
Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的,如:FROM scratch、FROM centos
1.定制 centos
使自己的镜像具备:登陆后的默认路径、vim 编辑器、查看网络配置 ifconfig 支持。
[root@docker ~]# cat /root/Dockerfile FROM centos MAINTAINER cool ENV MYPATH /usr/local WORKDIR $MYPATH #RUN yum -y install vim && yum -y install net-tools EXPOSE 80 CMD echo $MYPATH CMD echo "success--------------ok" CMD /bin/bash
执行构建
[root@docker ~]# docker build -t mycentos:v1 . Sending build context to Docker daemon 135.6MB Step 1/8 : FROM centos latest: Pulling from library/centos 7a0437f04f83: Pull complete Digest: sha256:5528e8b1b1719d34604c87e11dcd1c0a20bedf46e83b5632cdeac91b8c04efc1 Status: Downloaded newer image for centos:latest ---> 300e315adb2f Step 2/8 : MAINTAINER cool ---> Running in 82a7445835b0 Removing intermediate container 82a7445835b0 ---> 9446850f40bb Step 3/8 : ENV MYPATH /usr/local ---> Running in c21a219e7d97 Removing intermediate container c21a219e7d97 ---> 5f492cb19edd Step 4/8 : WORKDIR $MYPATH ---> Running in d9b69face3b6 Removing intermediate container d9b69face3b6 ---> 5b382d0ca5e3 Step 5/8 : EXPOSE 80 ---> Running in 2e89881caea1 Removing intermediate container 2e89881caea1 ---> 0f31c9075d11 Step 6/8 : CMD echo $MYPATH ---> Running in c9c195027b26 Removing intermediate container c9c195027b26 ---> 9257d8eca413 Step 7/8 : CMD echo "success--------------ok" ---> Running in 001575def3b7 Removing intermediate container 001575def3b7 ---> 4eff2c186253 Step 8/8 : CMD /bin/bash ---> Running in 278ebe23db29 Removing intermediate container 278ebe23db29 ---> 09027046867b Successfully built 09027046867b Successfully tagged mycentos:v1
验证是否支持所需功能
[root@docker ~]# docker run -it mycentos:v1
[root@62cc6e85723f local]# pwd
/usr/local
[root@6f70e65f3cb9 local]# vim --verison VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Dec 15 2020 16:44:08) Unknown option argument: "--verison" More info with: "vim -h"
查看镜像变更历史
[root@docker ~]# docker history mycentos:v1 IMAGE CREATED CREATED BY SIZE COMMENT 09027046867b 15 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B 4eff2c186253 15 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B 9257d8eca413 15 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B 0f31c9075d11 15 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B 5b382d0ca5e3 15 minutes ago /bin/sh -c #(nop) WORKDIR /usr/local 0B 5f492cb19edd 15 minutes ago /bin/sh -c #(nop) ENV MYPATH=/usr/local 0B 9446850f40bb 15 minutes ago /bin/sh -c #(nop) MAINTAINER cool 0B 300e315adb2f 6 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B <missing> 6 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B <missing> 6 months ago /bin/sh -c #(nop) ADD file:bd7a2aed6ede423b7… 209MB
7.4 自定义tomcat9镜像
环境准备
Tomcat9.0.48及jdk下载地址
https://mirrors.bfsu.edu.cn/apache/tomcat/tomcat-9/v9.0.48/bin/apache-tomcat-9.0.48.tar.gz
[root@docker ~]# wget https://mirrors.bfsu.edu.cn/apache/tomcat/tomcat-9/v9.0.48/bin/apache-tomcat-9.0.48.tar.gz --2021-07-01 14:47:10-- https://mirrors.bfsu.edu.cn/apache/tomcat/tomcat-9/v9.0.48/bin/apache-tomcat-9.0.48.tar.gz Resolving mirrors.bfsu.edu.cn (mirrors.bfsu.edu.cn)... 39.155.141.16, 2001:da8:20f:4435:4adf:37ff:fe55:2840 Connecting to mirrors.bfsu.edu.cn (mirrors.bfsu.edu.cn)|39.155.141.16|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 11489338 (11M) [application/octet-stream] Saving to: ‘apache-tomcat-9.0.48.tar.gz’ 100%[========================>] 11,489,338 18.3MB/s in 0.6s 2021-07-01 14:47:11 (18.3 MB/s) - ‘apache-tomcat-9.0.48.tar.gz’ saved [11489338/11489338] [root@docker ~]# ls anaconda-ks.cfg jdk-8u271-linux-x64.tar.gz apache-tomcat-9.0.48.tar.gz nginx1.0.tar Dockerfile
[root@docker ~]# tar zxvf apache-tomcat-9.0.48.tar.gz [root@docker ~]# tar zxvf jdk-8u271-linux-x64.tar.gz
编辑mydockerfile文件
[root@docker ~]# vi mydockerfile FROM centos MAINTAINER cool # 把宿主机当前目录下的jdk1.8.0_271 拷贝到容器 /usr/local/ 路径下 COPY jdk1.8.0_271/ /usr/local/jdk1.8.0_271/ # 把宿主机当前目录下的 tomcat 添加到容器 /usr/local/ 路径下 ADD apache-tomcat-9.0.48.tar.gz /usr/local/ # 安装vim编辑器 # RUN yum -y install vim # 设置工作访问时候的 WORKDIR 路径,登录落脚点 ENV MYPATH /usr/local WORKDIR $MYPATH # 配置 java 与 tomcat 环境变量 ENV JAVA_HOME /usr/local/jdk1.8.0_271 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.48 ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.48 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin # 容器运行时监听的端口 EXPOSE 8080 # 启动时运行 tomcat # ENTRYPOINT ["/usr/local/apache-tomcat-9.0.48/bin/startup.sh" ] CMD ["/usr/local/apache-tomcat-9.0.48/bin/catalina.sh","run"] #在root目录下执行构建
[root@docker ~]# docker build -f mydockerfile -t tomcat:v1 . Sending build context to Docker daemon 662.9MB Step 1/13 : FROM centos ---> 300e315adb2f Step 2/13 : MAINTAINER cool ---> Using cache ---> 9446850f40bb Step 3/13 : COPY jdk1.8.0_271/ /usr/local/jdk1.8.0_271/ ---> 20568f3f4fbe Step 4/13 : ADD apache-tomcat-9.0.48.tar.gz /usr/local/ ---> 9b7c825ad86c Step 5/13 : ENV MYPATH /usr/local ---> Running in e079169ea488 Removing intermediate container e079169ea488 ---> d46acf14c46c Step 6/13 : WORKDIR $MYPATH ---> Running in 9ae877a41635 Removing intermediate container 9ae877a41635 ---> e9cf7958262f Step 7/13 : ENV JAVA_HOME /usr/local/jdk1.8.0_271 ---> Running in b0920ba5971d Removing intermediate container b0920ba5971d ---> 574d51b04756 Step 8/13 : ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ---> Running in 239e02769114 Removing intermediate container 239e02769114 ---> 50fd498b40aa Step 9/13 : ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.48 ---> Running in 816ab551dcc1 Removing intermediate container 816ab551dcc1 ---> cc48d8d9b702 Step 10/13 : ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.48 ---> Running in 65751aeb2f11 Removing intermediate container 65751aeb2f11 ---> 9989b803fecc Step 11/13 : ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin ---> Running in cf97c44aedbf Removing intermediate container cf97c44aedbf ---> 021742e7fb5b Step 12/13 : EXPOSE 8080 ---> Running in 3eb06c8062b3 Removing intermediate container 3eb06c8062b3 ---> ad9fd6b3cee8 Step 13/13 : CMD ["/usr/local/apache-tomcat-9.0.48/bin/catalina.sh","run"] ---> Running in 84de0026e8c2 Removing intermediate container 84de0026e8c2 ---> 957618a3b196 Successfully built 957618a3b196 Successfully tagged tomcat:v1
运行查看效果
[root@docker ~]# docker run -d -p 8080:8080 --privileged=true --name tomcat9 -v /tmp/tomcat9logs/:/usr/local/apache-tomcat-9.0.48/logs tomcat:v1 1993fae7328a1a5036fd54a29f70d8ebb0a4f3e6f37364b58e795213a72b2665
浏览器访问ip+映射的端口
http://192.168.174.29:8080/