Docker 包括三个基本概念:
- 镜像(Image):Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。
- 容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
- 仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像。
镜像是一种静态的结构,可以看成面向对象里面的类,而容器是镜像的一个实例。
镜像包含着容器运行时所需要的代码以及其它组件,它是一种分层结构,每一层都是只读的(read-only layers)。构建镜像时,会一层一层构建,前一层是后一层的基础。镜像的这种分层存储结构很适合镜像的复用以及定制。
构建容器时,通过在镜像的基础上添加一个可写层(writable layer),用来保存着容器运行过程中的修改。
解决的问题由于不同的机器有不同的操作系统,以及不同的库和组件,在将一个应用部署到多台机器上需要进行大量的环境配置操作。
Docker 主要解决环境配置问题,它是一种虚拟化技术,对进程进行隔离,被隔离的进程独立于宿主操作系统和其它隔离的进程。使用 Docker 可以不修改应用程序代码,不需要开发人员学习特定环境下的技术,就能够将现有的应用程序部署在其它机器上。
Docker的优势 启动速度
启动虚拟机需要先启动虚拟机的操作系统,再启动应用,这个过程非常慢;
而启动 Docker 相当于启动宿主操作系统上的一个进程。
占用资源虚拟机是一个完整的操作系统,需要占用大量的磁盘、内存和 CPU 资源,一台机器只能开启几十个的虚拟机。
而 Docker 只是一个进程,只需要将应用以及相关的组件打包,在运行时占用很少的资源,一台机器可以开启成千上万个 Docker。
更容易迁移提供一致性的运行环境。已经打包好的应用可以在不同的机器上进行迁移,而不用担心环境变化导致无法运行。
更容易维护使用分层技术和镜像,使得应用可以更容易复用重复的部分。复用程度越高,维护工作也越容易。
更容易扩展可以使用基础镜像进一步扩展得到新的镜像,并且官方和开源社区提供了大量的镜像,通过扩展这些镜像可以非常容易得到我们想要的镜像。
安装- 环境查看
# 系统内核 [root@localhost /]# uname -r 3.10.0-1160.11.1.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"
- 安装文档链接:https://docs.docker.com/engine/install/centos/
- 卸载旧的版本
yum remove docker
docker-client
docker-client-latest
docker-common
docker-latest
docker-latest-logrotate
docker-logrotate
docker-engine
- 安装需要的安装包(提供实用程序)
yum install -y yum-utils # 若安装失败,可能是网络问题 # ping www.baidu.com失败,结果发现是(DNS文件没有配置) # # vi /etc/resolv.conf # nameserver 8.8.8.8 # nameserver 8.8.4.4
- 设置镜像的仓库
# 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
- 安装最新版本的Docker 引擎和容器
# 可以先更新yum软件包索引 yum makecache fast # 安装docker yum install docker-ce docker-ce-cli containerd.io
- 启动docker
systemctl start docker # 查看是否安装成功 docker version
- 测试:通过运行映像验证 Docker 引擎安装是否正确
docker run hello-world
- 查看下载的hello-world镜像
[root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest bf756fb1ae65 13 months ago 13.3kB
- 了解:卸载docker
# 卸载 Docker 引擎、CLI 和容器包 yum remove docker-ce docker-ce-cli containerd.io # 删除资源 rm -rf /var/lib/docker # /var/lib/docker docker默认工作路径
常用命令 帮助命令
docker version # 显示docker的版本信息 docker info # 显示docker的系统信息(包括镜像和容器的数量) docker --help # 查看所有的命令 docker import --help #查看目录的帮助 # 帮助文档:https://docs.docker.com/reference/镜像命令
- docker images:查看所有本地主机上的镜像
[root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest bf756fb1ae65 13 months ago 13.3kB ----------------------------------------------------------------- # 说明 REPOSITORY # 镜像的仓库源 TAG # 镜像的标签 IMAGE ID # 镜像的id CREATED # 镜像创建的时间 SIZE # 镜像的大小 # 可选项 Options: -a, --all # 列出所有镜像 -q, --quiet # 只显示镜像id -------------------------------------------------------------------- # 测试 [root@localhost ~]# docker images -a REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest bf756fb1ae65 13 months ago 13.3kB [root@localhost ~]# docker images -q bf756fb1ae65
- docker search:搜索镜像
[root@localhost ~]# docker search mysql ..................列出在dockerhub搜索的结果(name,description,stars等)..................... ------------------------------------------------------------------------- # 可选项 Options: -f, --filter filter 过滤条件 ------------------------------------------------------------------------- # 测试 [root@localhost ~]# docker search mysql --filter=STARS=3000 ..................搜索出来的镜像STARS数大于3000的.....................................
- docker pull:下载镜像
# docker pull 镜像名[:tag] [root@localhost ~]# docker pull mysql Using default tag: latest # 如果不写tag,默认就是latest最新版 latest: Pulling from library/mysql 45b42c59be33: Pull complete # 分层下载,docker image的核心,联合文件系统 b4f790bd91da: Pull complete 325ae51788e9: Pull complete adcb9439d751: Pull complete 174c7fe16c78: Pull complete 698058ef136c: Pull complete 4690143a669e: Pull complete f7599a246fd6: Pull complete 35a55bf0c196: Pull complete 790ac54f4c47: Pull complete 18602acc97e1: Pull complete 365caa3500d0: Pull complete Digest: sha256:b1cc887ed32cc6c2f217b12703bd05f503f2037892c8bb226047fe5dff85a109 # 签名 Status: Downloaded newer image for mysql:latest docker.io/library/mysql:latest # 真实地址 ------------------------------------------------------------------ # 指定版本下载 [root@localhost ~]# docker pull mysql:5.7 5.7: Pulling from library/mysql 45b42c59be33: Already exists # 有与刚刚下载的mysql最新版重合的,故不用下载 b4f790bd91da: Already exists # 节省了内存(联合文件系统的优势) 325ae51788e9: Already exists adcb9439d751: Already exists 174c7fe16c78: Already exists 698058ef136c: Already exists 4690143a669e: Already exists 66676c1ab9b3: Pull complete 25ebf78a38b6: Pull complete 349a839d5e27: Pull complete 40b03e3e5980: Pull complete Digest: sha256:853105ad984a9fe87dd109be6756e1fbdba8b003b303d88ac0dda6b455f36556 Status: Downloaded newer image for mysql:5.7 docker.io/library/mysql:5.7 ------------------------------------------------------------------- # 等价 docker pull mysql docker pull docker.io/library/mysql:latest
- docker rmi:删除镜像
# docker rmi -f 镜像id 删除指定镜像 # docker rmi -f 镜像id 镜像id 镜像id 镜像id 删除多个指定镜像 # docker rmi -f 镜像id $(docker images -aq) 删除全部镜像 --------------------------------------------------------------------------- # 测试 [root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mysql 5.7 5f47254ca581 21 hours ago 449MB mysql latest 2933adc350f3 21 hours ago 546MB hello-world latest bf756fb1ae65 13 months ago 13.3kB [root@localhost ~]# docker rmi -f 5f47254ca581 # 删除指定 Untagged: mysql:5.7 Untagged: mysql@sha256:853105ad984a9fe87dd109be6756e1fbdba8b003b303d88ac0dda6b455f36556 Deleted: sha256:5f47254ca5817f99cdd387ce7345d43e770e0682a4c81b62776f3347551b1d85 ...... [root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mysql latest 2933adc350f3 21 hours ago 546MB hello-world latest bf756fb1ae65 13 months ago 13.3kB [root@localhost ~]# docker rmi -f $(docker images -aq) # 删除全部 Untagged: mysql:latest Untagged: mysql@sha256:b1cc887ed32cc6c2f217b12703bd05f503f2037892c8bb226047fe5dff85a109 Deleted: sha256:2933adc350f3b62c05a66f700fba68ef93997d67263121250ec7848c50dcf3f5 ...... [root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE
容器命令
- 说明:有了镜像才能创建容器
# 下载centos镜像来测试学习 docker pull centos
- 新建容器并启动
docker run [可选参数] image # 参数说明 --name="Name" # 容器名字(用来区分容器) -d # 后台方式运行 -it # 交互方式运行(进入容器查看内容) -p # 指定容器端口 -p 主机端口:容器端口(常用) # 将容器中的某个端口映射到本地的某个端口上 -P # 随机指定端口 ----------------------------------------------------------------------------- # 启动并进入容器 [root@localhost ~]# docker run -it centos /bin/bash [root@83089d026ece /]# ls bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var # 从容器中退回主机 [root@83089d026ece /]# exit exit
- 退出容器
exit # 退出并停止容器 Ctrl+P+Q # 退出不停止容器
- 列出所有运行的容器
docker ps # 列出当前所有运行的容器 docker ps -a # 列出当前所有运行的容器 + 过去运行的容器 docker ps -aq # -q : 只显示容器编号
- 删除容器
docker rm 容器id # 删除指定容器(不能删除正在运行的容器) docker rm -f 容器id # 删除指定容器(可以强制删除正在运行的容器) docker rm -f $(docker ps -aq) # 删除所有容器
- 启动和停止容器
docker start 容器id # 启动容器 docker restart 容器id # 重启容器 docker stop 容器id # 停止当前正在运行的容器 docker kill 容器id # 强制停止当前正在运行的容器
- 问题
# 使用后台方式运行容器 docker run -d centos # 但查看时发现容器没有运行 docker ps # 原因:docker发现没有应用,会自动停止
- 查看日志
docker logs -f -t 容器编号 # 显示所有日志 docker logs -f -t --tail 条数 容器编号 # 显示指定条数日志 # 测试 [root@localhost ~]# docker logs -f -t --tail 10 ca683a40c363
- 查看容器中的进程信息
docker top 容器id [root@localhost ~]# docker top ca683a40c363
- 查看镜像的元数据
docker inspect 容器id
- 进入当前正在运行的容器
# 方式一 : docker exec -it 容器id /bin/bash [root@localhost ~]# docker ps ConTAINER ID IMAGE COMMAND ca683a40c363 centos "/bin/bash" [root@localhost ~]# docker exec -it ca683a40c363 /bin/bash [root@ca683a40c363 /]# ls bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var [root@ca683a40c363 /]# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 14:16 pts/0 00:00:00 /bin/bash root 15 0 0 14:38 pts/1 00:00:00 /bin/bash root 30 15 0 14:39 pts/1 00:00:00 ps -ef # 方式二 : docker attach 容器id [root@localhost ~]# docker attach ca683a40c363 。。。。。。正在执行的代码。。。。。。 ---------------------------------------------------------------------------- docker exec # 进入容器后开启一个新的终端,可以在里面操作(常用) docker attach # 进入容器正在执行的终端,不会开启新的进程
- 从容器内拷贝文件到主机
[root@localhost home]# docker attach ca683a40c363 [root@ca683a40c363 /]# cd /home [root@ca683a40c363 home]# ls [root@ca683a40c363 home]# touch first_test.java # 新建文件 [root@ca683a40c363 home]# ls first_test.java [root@ca683a40c363 home]# exit exit # 容器停止也没关系,只要存在就能拷贝 [root@localhost home]# docker cp ca683a40c363:/home/first_test.java /home [root@localhost home]# ls first_test.java
部署实战 部署nginx
1、搜索镜像(docker hub或使用docker search)
2、docker pull nginx
3、运行测试
# -d 后台运行 --name 给容器命名 -p 主机端口:容器端口 [root@localhost ~]# docker run -d --name nginx01 -p 3344:80 nginx eb9f48472ee95a78b144180884e2207bf3ab37d55beae4564411ae66df036bdc [root@localhost ~]# docker ps ConTAINER ID IMAGE COMMAND PORTS NAMES eb9f48472ee9 nginx "/docker-entrypoint.…" 0.0.0.0:3344->80/tcp nginx01 [root@localhost ~]# curl localhost:3344 # 进入容器 [root@localhost ~]# docker exec -it nginx01 /bin/bash root@eb9f48472ee9:/# whereis nginx nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx root@eb9f48472ee9:/# cd /etc/nginx root@eb9f48472ee9:/etc/nginx# ls conf.d fastcgi_params koi-utf koi-win mime.types modules nginx.conf scgi_params uwsgi_params win-utf # 停止容器 root@eb9f48472ee9:/etc/nginx# exit exit [root@localhost ~]# docker stop nginx01 # stop 容器id或容器names nginx01
部署tomcat
# 测试使用命令 docker run -it --rm tomcat:9.0 # docker run -it --rm 用完就删除容器(一般测试时使用)(删除后镜像还在)
# 一般使用 docker pull tomcat:9.0 docker run -d -p 3355:8080 --name tomcat01 tomcat:9.0 # 测试访问时发现无法访问 # 发现问题 [root@localhost ~]# docker exec -it tomcat01 /bin/bash root@4b6db47cca38:/usr/local/tomcat# ls BUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps.dist CONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps work root@4b6db47cca38:/usr/local/tomcat# cd webapps root@4b6db47cca38:/usr/local/tomcat/webapps# ls # webapps目录下为空(因为阿里云镜像只是保证最小可运行环境) # 应用都放在webapps.dist目录下 root@4b6db47cca38:/usr/local/tomcat/webapps# cd .. root@4b6db47cca38:/usr/local/tomcat# ls BUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps.dist CONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps work root@4b6db47cca38:/usr/local/tomcat# cd webapps.dist/ root@4b6db47cca38:/usr/local/tomcat/webapps.dist# ls ROOT docs examples host-manager manager # 进行拷贝 root@4b6db47cca38:/usr/local/tomcat# cp -r webapps.dist/* webapps
部署es
# es非常耗内存 docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.1 # 查看cpu占用 docker stats 969c0b25f00e # 修改配置 docker run -d --name elasticsearch01 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx256m" elasticsearch:7.6.1 docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx128m" -v /mydata/elasticsearch/data:/usr/share/elasticsearch/data -v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins elasticsearch:7.6.1 # 访问 curl localhost:9200
docker可视化
- 安装portainer(docker图形化界面管理工具)
docker run -d -p 9000:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer # 访问测试 http://192.168.132.3:9000
镜像原理
镜像:
镜像是一种轻量级、可执行的独立软件保,用来打包软件运行环境和基于运行环境开发的软件,他包含运行某个软件所需的所有内容,包括代码、运行时库、环境变量和配置文件
联合文件系统
UnionFs(联合文件系统):Union文件系统(UnionFs)是一种分层、轻量级并且高性能的文件系统,他支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下( unite several directories into a single virtual filesystem)。Union文件系统是 Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
Docker镜像加载原理:
docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。
boots(boot file system)主要包含 bootloader和 Kernel, bootloader主要是引导加 kernel, Linux刚启动时会加bootfs文件系统,在 Docker镜像的最底层是 boots。这一层与我们典型的Linux/Unix系统是一样的,包含boot加載器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs转交给内核,此时系统也会卸载bootfs。
rootfs(root file system),在 bootfs之上。包含的就是典型 Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。 rootfs就是各种不同的操作系统发行版,比如 Ubuntu, Centos等等。
分层理解:
所有的 Docker镜像都起始于一个基础镜像层,当进行修改或培加新的内容时,就会在当前镜像层之上,创建新的镜像层。
特点:
Docker 镜像都是只读的,当容器启动时,一个新的可写层加载到镜像的顶部!
这一层就是我们通常说的容器层,容器之下的都叫镜像层!
commit镜像
docker commit 提交容器成为一个新的副本 docker commit -m"提交的描述信息" -a"作者" 容器id 目标镜像名:tag
# 测试 1、启动一个默认的tomcat 2、发现没有webapps 3、进行拷贝 4、使用commit提交该修改过的镜像 # 类似于VM里的快照
容器数据卷
在Docker容器的实际使用中,经常会遇到容器的数据持久化,容器之间的数据共享等问题,通常我们有两种解决方案:
- 1、数据卷(Data Volumes):就是将容器内数据直接映射到本地主机环境的指定文件目录之中,可以理解为容器挂载一个虚拟数据卷然后映射到一个主机目录中
- 2、数据卷容器(Data Volume Containers):用专门的容器来挂载数据卷,其他容器通过挂载这个父容器来实现数据共享,这个专门挂载数据卷的容器就是数据卷容器,简单的总结就是有一个容器来专门管理数据的持久化和容器之间数据共享
前者常用于单一容器数据持久化,后者常用于多容器之间的数据共享和数据持久化
数据卷
方式一:直接使用命令来挂载 -v
docker run -it -v 主机目录:容器目录
# 测试 [root@localhost ~]# docker run -it -v /home/test:/home centos /bin/bash
# 可通过docker inspect 容器id 查看是否挂载
"Mounts": [
{
"Type": "bind",
"Source": "/home/test",
"Destination": "/home",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
实战MySQL
- 解决MySQL数据持久化问题
-d 后台运行 -p 端口映射 -v 数据卷挂载 -e 环境配置 --name 容器名字 [root@localhost ~]# docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name my_mysql mysql:5.7
初始DockerFile
方式二:生成一个镜像时就进行挂载
[root@localhost docker-test-volume]# pwd /home/docker-test-volume # 编写dockerfile文件 [root@localhost docker-test-volume]# vim dockerfile1 [root@localhost docker-test-volume]# cat dockerfile1 FROM centos VOLUME ["volume1","volume2"] # 匿名挂载 CMD echo "----end----" CMD /bin/bash # 构建镜像 [root@localhost docker-test-volume]# docker build -f dockerfile1 -t kim/centos . Successfully built 684169834073 Successfully tagged kim/centos:latest [root@localhost docker-test-volume]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE kim/centos latest 684169834073 52 seconds ago 209MB
# 启动容器 [root@localhost docker-test-volume]# docker run -it 684169834073 /bin/bash [root@2a70b06f1bdc /]# ls -l total 0 lrwxrwxrwx 1 root root 7 Nov 3 15:22 bin -> usr/bin drwxr-xr-x 5 root root 360 Feb 17 15:22 dev drwxr-xr-x 1 root root 66 Feb 17 15:22 etc drwxr-xr-x 2 root root 6 Nov 3 15:22 home lrwxrwxrwx 1 root root 7 Nov 3 15:22 lib -> usr/lib lrwxrwxrwx 1 root root 9 Nov 3 15:22 lib64 -> usr/lib64 drwx------ 2 root root 6 Dec 4 17:37 lost+found drwxr-xr-x 2 root root 6 Nov 3 15:22 media drwxr-xr-x 2 root root 6 Nov 3 15:22 mnt drwxr-xr-x 2 root root 6 Nov 3 15:22 opt dr-xr-xr-x 115 root root 0 Feb 17 15:22 proc dr-xr-x--- 2 root root 162 Dec 4 17:37 root drwxr-xr-x 11 root root 163 Dec 4 17:37 run lrwxrwxrwx 1 root root 8 Nov 3 15:22 sbin -> usr/sbin drwxr-xr-x 2 root root 6 Nov 3 15:22 srv dr-xr-xr-x 13 root root 0 Feb 17 14:49 sys drwxrwxrwt 7 root root 145 Dec 4 17:37 tmp drwxr-xr-x 12 root root 144 Dec 4 17:37 usr drwxr-xr-x 20 root root 262 Dec 4 17:37 var drwxr-xr-x 2 root root 6 Feb 17 15:22 volume1 # 生成镜像时自动挂载(数据卷目录) drwxr-xr-x 2 root root 6 Feb 17 15:22 volume2
# 查看外部同步的目录
# 使用docker inspect查看卷挂载的路径
"Mounts": [
{
"Type": "volume",
"Name": "3d62dfe2c6f5da3091d52cc64f105c98e4196c1861d1544d9bac2be8a8391c30",
"Source": "/var/lib/docker/volumes/3d62dfe2c6f5da3091d52cc64f105c98e4196c1861d1544d9bac2be8a8391c30/_data", 容器外的数据卷目录
"Destination": "volume2",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "2e889d6623ada2313d0502f6e2a9d702a4995551994f42a37eefc12dee358220",
"Source": "/var/lib/docker/volumes/2e889d6623ada2313d0502f6e2a9d702a4995551994f42a37eefc12dee358220/_data", 容器外的数据卷目录
"Destination": "volume1",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
[root@localhost _data]# cd /var/lib/docker/volumes/2e889d6623ada2313d0502f6e2a9d702a4995551994f42a37eefc12dee358220/_data
[root@localhost _data]# ls
container.txt
数据卷容器
-
作用:实现容器间的数据共享
-
应用:多个mysql同步数据
# docker01作为父容器 [root@localhost ~]# docker run -it --name docker01 kim/centos [root@467f8f8d46af /]# ls -l ...... drwxr-xr-x 2 root root 6 Feb 18 01:49 volume1 drwxr-xr-x 2 root root 6 Feb 18 01:49 volume2 [root@localhost ~]# docker run -it --name docker02 --volumes-from docker01 kim/centos [root@localhost ~]# docker run -it --name docker03 --volumes-from docker01 kim/centos
DockerFile
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
命令FROM # 基础镜像 MAINTAINER # 维护者信息(姓名+邮箱) COPY # 复制指令,将文件拷贝到镜像中 ADD # 添加内容 WORKDIR # 镜像的工作目录 VOLUME # 挂载目录 EXPOSE # 暴露端口(与-p作用相同) RUN # 镜像构建时需要运行的命令 ENV # 设置环境变量 CMD # 指定容器启动时要运行的命令 # 类似于 RUN 指令,用于运行程序,但二者运行的时间点不同: # CMD 在 docker run 时运行 # RUN 是在 docker build ENTRYPOINT # 类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖(即只有最后一个生效),而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序(即可追加命令) onBUILD # 在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这是执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 onBUILD 指定的命令。
构建centos
- 初始(无法使用vim、ifconfig等)
[root@localhost ~]# docker run -it centos [root@0fda862a6d76 /]# vim bash: vim: command not found [root@0fda862a6d76 /]# ifconfig bash: ifconfig: command not found
- 添加内容
# 编写DockerFile的文件 [root@localhost dockerfile]# vim my_centos [root@localhost dockerfile]# cat my_centos FROM centos MAINTAINER KimTou<752160655@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 # 通过文件构建镜像 [root@localhost dockerfile]# docker build -f my_centos -t mycentos:1.0 . # docker bild -f dockerfile文件路径 -t 镜像名:[tag] . # 运行测试 [root@localhost dockerfile]# docker run -it mycentos:1.0 [root@3ee183346afd local]# pwd /usr/local [root@3ee183346afd local]# ifconfig # 查看本地变更历史 docker history 镜像id
CMD与ENTRYPOINT
- 测试CMD
# 编写dockerfile文件 [root@localhost dockerfile]# vim dockerfile-cmd-test FROM centos CMD ["ls","-a"] # 构建镜像 [root@localhost dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest . Successfully built 23e5ab5b3d93 Successfully tagged cmdtest:latest # run运行,发现 ls -a 命令生效 [root@localhost dockerfile]# docker run 23e5ab5b3d93 . .. .dockerenv bin dev etc home 等等 # 此时追加一个命令"-l"(即为了形成ls -al),却报错 [root@localhost dockerfile]# docker run 23e5ab5b3d93 -l docker: Error response from daemon: OCI runtime create failed: container_linux.go:370: starting container process caused: exec: "-l": executable file not found in $PATH: unknown. # 原因分析:CMD的情况下,-l替换了CMD ["ls","-a"]命令,而-l不是命令,所以报错 # 想正确执行,需使用 [root@localhost dockerfile]# docker run 23e5ab5b3d93 ls -al
- 测试ENTRYPOINT
[root@localhost dockerfile]# vim dockerfile-cmd-entrypoint FROM centos ENTRYPOINT ["ls","-a"] [root@localhost dockerfile]# docker build -f dockerfile-cmd-entrypoint -t entrypoint . Successfully built fd019392b084 Successfully tagged entrypoint:latest [root@localhost dockerfile]# docker run fd019392b084 . .. .dockerenv bin dev etc home 等等 # 进行追加命令,直接拼接在ENTRYPOINT命令后面 [root@localhost dockerfile]# docker run fd019392b084 -l total 0 drwxr-xr-x 1 root root 6 Feb 17 14:54 . drwxr-xr-x 1 root root 6 Feb 17 14:54 .. -rwxr-xr-x 1 root root 0 Feb 17 14:54 .dockerenv lrwxrwxrwx 1 root root 7 Nov 3 15:22 bin -> usr/bin drwxr-xr-x 5 root root 340 Feb 17 14:54 dev drwxr-xr-x 1 root root 66 Feb 17 14:54 etc drwxr-xr-x 2 root root 6 Nov 3 15:22 home 等等
制作tomcat镜像
1、准备镜像文件,tomcat压缩包、jdk压缩包
[root@localhost tomcat]# ls apache-tomcat-9.0.38.tar.gz jdk-8u281-linux-x64.tar.gz [root@localhost tomcat]# pwd /home/build/tomcat
2、编写dockerfile文件( 名字为Dockerfile,build就会自动寻找,不需要使用 -f 命令来指定)
FROM centos MAINTAINER KimTou<752160655@qq.com> COPY README.txt /usr/loacl/README.txt ADD jdk-8u281-linux-x64.tar.gz /usr/local ADD apache-tomcat-9.0.38.tar.gz /usr/local RUN yum -y install vim ENV MYPATH /usr/local WORKDIR $MYPATH ENV JAVA_HOME /usr/local/jdk1.8.0_281 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.38 ENV CATALINA_base /usr/local/apache-tomcat-9.0.38 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin EXPOSE 8080 CMD /usr/local/apache-tomcat-9.0.38/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.38/bin/logs/catalina.out
3、构建镜像
[root@localhost tomcat]# docker build -t diytomcat .
4、启动镜像
[root@localhost tomcat]# docker run -d -p 8080:8080 --name diytomcat -v /home/build/tomcat/test:/usr/local/apache-tomcat-9.0.38/webapps/test -v /home/build/tomcat/tomcatlogs:/usr/local/apache-tomcat-9.0.38/logs diytomcat b894eae2b2f0ad6650c1ef15c1079f83f80539acb9ce2fc15f1f5c8f48cfc930 [root@localhost tomcat]# docker exec -it b894eae2b2f0a /bin/bash
5、访问测试
curl localhost:8080 # 内部测试 http://192.168.132.3:8080/ # 外部测试
6、发布项目(由于做了卷挂载,我们直接在本地编写项目就可以发布了)
[root@localhost tomcat]# ls apache-tomcat-9.0.38.tar.gz Dockerfile jdk-8u281-linux-x64.tar.gz README.txt test tomcatlogs [root@localhost tomcat]# cd test [root@localhost test]# ls [root@localhost test]# pwd /home/build/tomcat/test [root@localhost test]# mkdir WEB-INF [root@localhost test]# ls WEB-INF [root@localhost test]# cd WEB-INF/ [root@localhost WEB-INF]# vim web.xml[root@localhost WEB-INF]# cd .. [root@localhost test]# ls WEB-INF [root@localhost test]# vim index.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> hello,我的tomcat Hello World!
<% System.out.println("-----my test web logs-----"); %>
7、访问测试
http://192.168.132.3:8080/test/
发布镜像至DockerHub
- 登录
[root@localhost tomcat]# docker login --help
Usage: docker login [OPTIONS] [SERVER]
Log in to a Docker registry.
If no server is specified, the default is defined by the daemon.
Options:
-p, --password string Password
--password-stdin Take the password from stdin
-u, --username string Username
[root@localhost tomcat]# docker login -u kimtou
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
- docker push
[root@localhost tomcat]# docker push diytomcat Using default tag: latest The push refers to repository [docker.io/library/diytomcat] 0b5f6503d033: Preparing 1ca989e043c6: Preparing b0f9e083fd93: Preparing 13ab4cbc0c90: Preparing 2653d992f4ef: Preparing denied: requested access to the resource is denied # 拒绝(原因:本地没有tag信息) # 添加tag信息 [root@localhost tomcat]# docker tag a9181af1fc76(diytomcat镜像id) kimtou/tomcat:1.0 [root@localhost tomcat]# docker push kimtou/tomcat:1.0
Dokcer网络 理解docker0
# 查看内部网络地址 [root@localhost ~]# ip addr 1: lo:mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo # 本机回环地址 valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:8b:8f:c6 brd ff:ff:ff:ff:ff:ff # 虚拟机内网地址 inet 192.168.132.3/24 brd 192.168.132.255 scope global noprefixroute ens33 valid_lft forever preferred_lft forever inet6 fe80::b337:5b2f:b8aa:54f7/64 scope link noprefixroute valid_lft forever preferred_lft forever 3: docker0: mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:40:82:c8:42 brd ff:ff:ff:ff:ff:ff inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 # docker0地址 valid_lft forever preferred_lft forever
- 三个网卡
[root@localhost ~]# docker run -d -P --name tomcat01 tomcat:9.0 e07dc049270c66313c2fa9d0bc3f59af5656012377ece17c887226fb68097716 # 查看容器的内部网络地址(不想进去/bin/bash,,只想查看网络地址,所以直接可以写ip addr) [root@localhost ~]# docker exec -it tomcat01 ip addr 1: lo:mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 4: eth0@if5: mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever # 发现得到一个 eth0@if5 ip地址(docker分配的) # 发现linux可以ping通容器内部 [root@localhost ~]# ping 172.17.0.2 PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data. 64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.295 ms
- 启动容器后,再次使用ip addr
[root@localhost ~]# ip addr 1: lo:mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:8b:8f:c6 brd ff:ff:ff:ff:ff:ff inet 192.168.132.3/24 brd 192.168.132.255 scope global noprefixroute ens33 valid_lft forever preferred_lft forever inet6 fe80::b337:5b2f:b8aa:54f7/64 scope link noprefixroute valid_lft forever preferred_lft forever 3: docker0: mtu 1500 qdisc noqueue state UP group default link/ether 02:42:40:82:c8:42 brd ff:ff:ff:ff:ff:ff inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 valid_lft forever preferred_lft forever inet6 fe80::42:40ff:fe82:c842/64 scope link valid_lft forever preferred_lft forever 5: veth2d24b84@if4: mtu 1500 qdisc noqueue master docker0 state UP group default link/ether 26:e5:f5:40:f9:dc brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet6 fe80::24e5:f5ff:fe40:f9dc/64 scope link valid_lft forever preferred_lft forever # 多了 5: veth2d24b84@if4 ,这个正好对应容器的 4: eth0@if5
- 启动另一个容器ping容器,发现可以ping通
[root@localhost ~]# docker run -d -P --name tomcat02 tomcat:9.0 db1d55c1d4888f7d91fe08acd742b149080982f221c7273c1c258fc8564e4add [root@localhost ~]# docker exec -it tomcat02 ping 172.17.0.2 PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data. 64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.132 ms
自定义网络
- 查看所有docker网络
[root@localhost ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 86c387d828ca bridge bridge local 804bff49826a host host local 6525353ed74f none null local
网络模式
- bridge : 桥接模式(默认)
- none : 不配置网络
- host : 与宿主机(Linux服务器)共享网络
# 两者作用相同,使用docker0 docker run -d -P --name tomcat01 tomcat:9.0 docker run -d -P --name tomcat01 --net bridge tomcat:9.0
- 创建自定义网络
# --driver bridge # --subnet 192.168.0.0/16 192.168.0.2 ~ 192.168.255.255 # --gateway 192.168.0.1 # 创建自定义网络 [root@localhost ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet 5e6793046451757d49b52b93be2d655dce9673b1b4abb72918de92b716d26654 [root@localhost ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 86c387d828ca bridge bridge local 804bff49826a host host local 5e6793046451 mynet bridge local 6525353ed74f none null local
- 使用我们的自定义网络
# 启动两个容器
[root@localhost ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat:9.0
df65ecd0612fc3e4c1e1337c4f58d0d49c0289ced365e89b3cf1a8b0bfb87be3
[root@localhost ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat:9.0
7b73264240aec380c1ab3deb7e6d3bf773570065a8c68216b348db7afa617745
[root@localhost ~]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "5e6793046451757d49b52b93be2d655dce9673b1b4abb72918de92b716d26654",
"Created": "2021-02-19T12:26:58.440470651+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": {
"7b73264240aec380c1ab3deb7e6d3bf773570065a8c68216b348db7afa617745": {
"Name": "tomcat-net-02",
"EndpointID": "9136cf64444aeb45fbb7809d884fcf05b84e8d2d07a89cf588b5df9e70f986dc",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16", 分配的ip地址
"IPv6Address": ""
},
"df65ecd0612fc3e4c1e1337c4f58d0d49c0289ced365e89b3cf1a8b0bfb87be3": {
"Name": "tomcat-net-01",
"EndpointID": "b8ff576a005ea18db3da7661e2e2fb65547bf4a61948bc54a3c7e74a163d0877",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16", 分配的ip地址
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
- 用处
# 自定义网络可以使用域名ping通,则默认的docker0不行 [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.159 ms [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.077 ms
- 同时也可以让不同的集群使用不同的网络,如redis集群使用192.160.0.0,mysql集群使用192.161.0.0
网络连通
- 尝试ping不同网段的容器(结果:无法ping)
[root@localhost ~]# docker exec -it tomcat01 ping tomcat-net-01 ping: tomcat-net-01: Name or service not known
- 打通docker0与mynet
[root@localhost ~]# docker network --help Usage: docker network COMMAND Manage networks 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
- 测试打通 tomcat01 到 mynet
# 作用:将 tomcat01 放到 mynet 网络下(一个容器两个ip)
[root@localhost ~]# docker network connect mynet tomcat01
# 查看mynet发现tomcat01已被加入
[root@localhost ~]# docker network inspect mynet
"Containers": {
"69e094144858a922928b9297bd5e59c2f04914f3138e0e31e9e5623daa594792": {
"Name": "tomcat01", 加入mynet
"EndpointID": "f4d4b6d389f7ceb223b60a41a8f751c283e8b0548c3a66dde632e7ccb89a11d0",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
},
"df65ecd0612fc3e4c1e1337c4f58d0d49c0289ced365e89b3cf1a8b0bfb87be3": {
"Name": "tomcat-net-01",
"EndpointID": "9247cf33ad07415038294d98de0875699ab0a4cd7d8c6099493eb4fdb4fd8230",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
}
},
SpringBoot微服务打包Docker镜像
1、创建SpringBoot项目
2、打包应用
3、编写dockerfile
FROM java:8 COPY *.jar app.jar CMD ["--server.port=8080"] EXPOSE 8080 ENTRYPOINT ["java","-jar","app.jar"]
4、构建镜像
[root@localhost idea]# ls docker-0.0.1-SNAPSHOT.jar Dockerfile [root@localhost idea]# docker build -t kim-springboot .
5、发布运行
[root@localhost idea]# docker run -d -P --name kim-springboot-web kim-springboot
4a0ac515eaac0100dc69c5ecc9b10562bc71c45902ac4f4aa79516a9ddb3d264
[root@localhost idea]# docker ps
ConTAINER ID IMAGE COMMAND PORTS NAMES
4a0ac515eaac kim-springboot "java -jar app.jar -…" 0.0.0.0:49162->8080/tcp kim-springboot-web
[root@localhost idea]# curl localhost:49162
{"timestamp":"2021-02-19T09:34:58.322+00:00","status":404,"error":"Not Found","message":"","path":"/"}[root@localhost idea]# curl localhost:49162/hello
hello,kim[root@localhost idea]#
安装Vim
当我们进入docker容器时,经常会发现容器内并没有安装vim,此时需要我们手动去进行安装。
1、apt-get update
2、apt-get install vim
3、cd /usr/share/vim/vim81
4、vim defaults.vim
# 在=前加-
if has('mouse')
set mouse-=a
endif
文章内容参考狂神说:https://www.bilibili.com/video/BV1og4y1q7M4



