这是我参与「掘金日新计划 · 2 月更文挑战」的第 十 九 天
Docker安装Nginx和Tomcat
Docker 安装Nginx
# 1、搜索镜像
docker search nginx
# 2、下载镜像
docker pull nginx
# 3、启动镜像、测试
# -d 后台运行
# --name 给容器命名
# -p 宿主机端口:容器内部端口
[root@chenstudy ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 3 months ago 141MB
centos latest 5d0da3dc9764 6 months ago 231MB
[root@chenstudy ~]# docker run -d --name nignx01 -p 8888:80 nginx
9d219c6953482f900862b6cace896fd23c3902a731747ba9622b7455724d2ae4
[root@chenstudy ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9d219c695348 nginx "/docker-entrypoint.…" 44 seconds ago Up 43 seconds 0.0.0.0:8888->80/tcp, :::8888->80/tcp nignx01
[root@chenstudy ~]# curl localhost:8888
# 进入容器
[root@chenstudy ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS
9d219c695348 nginx "/docker-entrypoint.…" 8 minutes ago Up 8 minutes
PORTS NAMES
0.0.0.0:8888->80/tcp, :::8888->80/tcp nignx01
[root@chenstudy ~]# docker exec -it nignx01 /bin/bash
root@9d219c695348:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@9d219c695348:/# cd /etc/nginx
root@9d219c695348:/etc/nginx# ls
conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params
root@9d219c695348:/etc/nginx#
Docker 安装Tomcat
# 官方的使用
docker run -it --rm tomcat:9.0
# 我们之前的启动都是后台启动,停止了容器之后,容器还可以查到docker run -it --rm 一般用来测试
# 先下载再启动
docker pull tomacat:9.0
# 启动运行
docker run -d -p 8888:8080 --name tomcat01 tomcat
# 测试访问没有问题
[root@chenstudy ~]# docker run -d -p 8888:8080 --name tomcat01 tomcat
# 进入容器
a49fcebf9d45e2bc54225a431a09bd2af7120469dbe7fbc89073cf90a618fcfc
[root@chenstudy ~]# docker exec -it tomcat01 /bin/bash
# 发现问题:1、Linux命令少了,2、没有webapps。阿里云镜像的原因,默认是最小的镜像
# 保证最小的可运行环境
部署es+kibana
# es 暴露的端口有很多,es十分耗内存,es的数据一般需要放置到安全目录!挂载
# --net somenetwork 网络配置
# 启动 elasticsearch
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.17.1
# 启动就卡住了 docker status 查看 CPU 的使用情况
# 查看docker stats
# 测试es是否能够成功
[root@chenstudy ~]# clear
[root@chenstudy ~]# curl localhost:9200
{
"name" : "eafdbc6f7434",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "_Be_dHgMQpqwll0t77WFiA",
"version" : {
"number" : "7.17.1",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "e5acb99f822233d62d6444ce45a4543dc1c8059a",
"build_date" : "2022-02-23T22:20:54.153567231Z",
"build_snapshot" : false,
"lucene_version" : "8.11.1",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
# 赶紧关闭,增加内存限制,修改配置文件 -e 环境配置修改
docker run -d --name elasticsearch02 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx256m" elasticsearch:7.17.1
# 查看 docker stats
# 测试是否启动成功
[root@chenstudy ~]# curl localhost:9200
{
"name" : "9b8a00629df9",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "xNu8NLAtRsavS1uYJJVNhw",
"version" : {
"number" : "7.17.1",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "e5acb99f822233d62d6444ce45a4543dc1c8059a",
"build_date" : "2022-02-23T22:20:54.153567231Z",
"build_snapshot" : false,
"lucene_version" : "8.11.1",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
可视化
- portainer(先用这个)
docker run -d -p 8088:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
- Rancher(CI/CD 再用)
什么是 portainer ?
Docker 图形化界面管理工具!提供一个后台界面供我们操作
docker run -d -p 8088:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
访问测试:http://ip:8088
选择挂载本地的:
登录之后的界面:
四、Docker镜像
4.1、镜像是什么?
镜像是一种轻量级、可执行的独立软件包,用来打包运行环境和基于运行环境的开发软件,它包含运行某个软件运行所需的所有内容,包括代码、运行时、库、环境变量和配置文件
所有的应用,直接打包docker镜像,就可以直接跑起来!
如何得到镜像:
- 从远程仓库下载
- 朋友拷贝给你
- 自己制作一个镜像DockerFile
4.2、Docker镜像加载原理
UnionFS(联合文件系统)
Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交,来一层层的叠加。 同时可以将不同目录,挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。 Union文件系统是Docker镜像的基础。 镜像可以通过分层来进行继承,基于基础镜像(没有父镜像概念),可以制作各种具体的应用镜像。 总结:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
Docker镜像加载原理
Docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS(联合文件系统)。
分为两个部分:
-
bootfs(boot file system):主要包含bootloader和kernel(Linux内核),bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统,而在Docker镜像的最底层也是bootfs这一层,这与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后,整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
即:系统启动时需要的引导加载,这个过程会需要一定时间。就是黑屏到开机之间的这么一个过程。电脑、虚拟机、Docker容器启动都需要的过程。在说回镜像,所以这一部分,无论是什么镜像都是公用的。
-
rootfs(root file system):rootfs在bootfs之上。包含的就是典型Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。
即:镜像启动之后的一个小的底层系统,这就是我们之前所说的,容器就是一个小的虚拟机环境,比如Ubuntu,Centos等,这个小的虚拟机环境就相当于rootfs。
平时我们安装进虚拟机的CentOS系统都是好几个G,为什么Docker这里才200M?
对于一个精简的OS系统,rootfs可以很小,只需要包含最基本的命令、工具和程序库就可以了,因为底层直接用Host(宿主机)的kernel(也就是宿主机或者服务器的boosfs+内核),自己只需要提供rootfs就可以了。
由此可见对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs部分。
虚拟机是分钟级别的,容器是秒级
4.3、分层理解
分层的镜像
我们可以去下载一个镜像,注意观察下载日志的输出,可以看到是一层一层的再下载!
思考:为什么Docker镜像要采用这种分层的结构呢?
最大的好处,我觉得莫过于资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。
查看镜像分层的方式可以通过docker image inspect 命令
{
// ......
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:2edcec3590a4ec7f40cf0743c15d78fb39d8326bc029073b41ef9727da6c851f",
"sha256:9b24afeb7c2f21e50a686ead025823cd2c6e9730c013ca77ad5f115c079b57cb",
"sha256:4b8e2801e0f956a4220c32e2c8b0a590e6f9bd2420ec65453685246b82766ea1",
"sha256:529cdb636f61e95ab91a62a51526a84fd7314d6aab0d414040796150b4522372",
"sha256:9975392591f2777d6bf4d9919ad1b2c9afa12f9a9b4d260f45025ec3cc9b18ed",
"sha256:8e5669d8329116b8444b9bbb1663dda568ede12d3dbcce950199b582f6e94952"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
理解:
所有的 Docker镜像都起始于一个基础镜像层,当进行修改或培加新的内容时,就会在当前镜像层之上,创建新的镜像层。
举一个简单的例子,假如基于 Ubuntu Linux16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加 Python包, 就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创健第三个镜像层该像当前已经包含3个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。
在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含3个文件,而镜像包含了来自两个镜像层的6个文件。
文种情況下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中
Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统
Linux上可用的存储引撃有AUFS、 Overlay2、 Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于 Linux中对应的 件系统或者块设备技术,井且每种存储引擎都有其独有的性能特点。
Docker在 Windows上仅支持 windowsfilter 一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW [1]。
下图展示了与系统显示相同的三层镜像。所有镜像层堆并合井,对外提供统一的视图
特点
Docker 镜像都是只读的,当容器启动时,一个新的可写层加载到镜像的顶部!
这一层就是我们通常说的容器层,容器之下的都叫镜像层!
4.4、commit镜像
docker commit 提交容器成为一个新的副本
# 命令和git原理类似
docker commit -m="提交的描述信息" -a="作者" 容器id, 目标镜像名,[TAG]
实战测试:
# 1、启动一个默认的tomcat
docker run -it -p 8080:8080 tomcat
# 2、发现这个默认的tomcat是没有webapps应用,镜像的原因,官方的镜像默认webapps下面是没有文件的
# 3、自己拷贝进去基本的文件
# 4、将我们操作过的容器通过commit提交为一个镜像!我们以后就使用我们修改过的镜像即可,这就是我们自己的一个修改过的镜像
入门Docker结束,开启进阶学习
五、容器数据卷
5.1、什么是容器数据卷
数据?如果数据都在容器中,那么我们容器删除,数据就会丢失!需求:数据持久化
MySQL,容器删了,就相当于删库跑路了,需求:MySQL数据可以存储在本地
容器之间可以有一个数据共享的技术,Docker中产生的数据,同步到本地
5.2、使用数据卷
方式一:直接使用命令来挂载 -v
docker run -it -v 主机目录,容器目录
# 测试
docker run -it -v /home/ceshi:/home centos /bin/bash
# 启动之后,我们可以通过docker inspect 查看容器的详细信息
测试文件同步
5.3、实战MySQL
思考:MySQL的数据持久化问题!
# 获取镜像
[root@chenstudy home]# docker pull mysql:5.7
# 运行容器时需要做数据挂载 安装启动MySQL时需要设置密码的这是要注意的
# 官方的 docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
# 启动
[root@chenstudy home]# docker run -d -p 8088:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=ZJch1328. --name mysql1 mysql:5.7
5.4、具名挂载和匿名挂载
# 匿名挂载
-v 容器内路径
docker run -d -P --name nginx01 -v /etc/nginx nginx
# 查看所有的 volume 的情况
[root@chenstudy mysql]# docker volume ls
local 79c37ba8f722b547003d715c8295eb44481d6bd927c77842123e4fe08406d764
# 这里发现,这种就是匿名挂载, 我们在 -v只写了容器内路径,没有写容器外的路径
# 具名挂载
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
[root@chenstudy mysql]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
8d8c7ce383aafe40b5fbd346de2380ec2e221c392f7dfc6873b16ffa17ec72a1
[root@chenstudy mysql]# docker volume ls
DRIVER VOLUME NAME
local juming-nginx
所有的docker内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/xxx
我们通过具名挂载可以方便的找到我们的一个卷,大多数情况下在使用具名挂载
# 如何确定时具名挂载还是匿名挂载,还是指定路径挂载
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /宿主级的路径:容器内路径 # 指定路径挂载
扩展:
# 通过-v容器内路径:ro|rw
ro: readonly # 只读
rw: readwrite # 可读可写
# 一旦设置了容器的权限,容器对我们挂载出来的内容就有限定了!
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
5.5、初始Dockerfile
Dockerfile就是用来构建docker镜像的构建文件!命令脚本!
通过脚本可以生成镜像,镜像时一层一层的,脚本时一个个的命令,每个命令是一层!
# dockerfile文件 文件名随机, 建议Dockerfile
# 文件内容指令(大写) 参数
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "-----end-----"
CMD /bin/bash
# 这里的每个命令,就是镜像的一层
# 启动自己写的镜像
docker run -it 3d2683f12a3d /bin/bash
5.6、数据卷容器
多个mysql同步数据!
# 测试,可以删除docker01,查看一下docker02和docker03是否可以访问这个文件
# 测试依旧可以访问
多个mysql实现数据共享
[root@chenstudy home]# docker run -d -p 8088:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=ZJch1328. --name mysql1 mysql:5.7
[root@chenstudy home]# docker run -d -p 8088:3306 -e MYSQL_ROOT_PASSWORD=ZJch1328. --name mysql2 --volumes-from mysql2 mysql:5.7
# 这个时候,可以实现两个容器数据同步!
六、DockerFile
6.1、DockerFile介绍
dockerfile是用来构建docker镜像的文件!命令参数脚本
构建步骤:
1、编写一个dockerfile文件
2、docker build构建成为一个镜像
3、docker run 运行镜像
4、docker push 发布镜像(Docker Hub、阿里云镜像仓库)
6.2、DockerFile构建过程
基础知识:
1、每个保留关键字(指令)都必须是大写字母
2、执行从上到下顺序执行
3、# 表示注释
4、每个指令都会创建提交一个新的镜像层,并提交
dockerfile是面向开发的,我们以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单!
步骤:开发,部署,运维...缺一不可
DockerFile:构建文件,定义了一切的步骤,源代码
DockerImages:通过DockerFile构建生成的镜像,最终发布和运行的产品
Docker容器:容器就是镜像运行起来提供服务器
6.3、DockerFile指令
FROM # 基础镜像,一切这里开始构建
MAINTAINER # 镜像是谁写的,姓名+邮箱
RUN #镜像构建时需要运行的命令
ADD # 步骤,tomcat镜像,这个tomcat压缩包!添加内容
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 暴露端口配置
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承的DockerFile 这个时候就会运行ONBUILD指令
COPY # 类似ADD,将我们的文件拷贝到镜像中
ENV # 构建的时候设置环境变量!
6.4、实战测试
Docker Hub中99%的镜像都是从这个基础镜像过来的FROM scratch,然后配置需要的软件和配置来进行构建
创建自己的centos
# 编写DockerFile的文件
FROM centos
MAINTAINER haochen<1065501674@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 "------end------"
CMD /bin/bash
# 2、通过这个文件构建镜像
# 命令 docker build -f dockerfile文件路径 -t 镜像名:[tag]
Successfully built 22dc06d87f2d
Successfully tagged mycentos:latest
# 测试运行
CMD 和 ENTRYPOINT 的区别
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
6.5、实战:tomcat镜像
1、准备镜像文件 tomcat压缩包,jdk压缩包!
2、编写dockerfile文件,官方命名Dockerfilebuild会自动寻找这个文件,就不需要-f指定了
FROM centos:7
MAINTAINER xiaofan<594042358@qq.com>
COPY readme.txt /usr/local/readme.txt
ADD jdk-8u73-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.37.tar.gz /usr/local/
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_73
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.37
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.37
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.37/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.37/bin/logs/catalina.out
1、构建镜像
docker build -t diytomcat .
2、启动镜像
docker run -d -p 8088:8080 --name chentomcat -v /home/chen/tomcat/test:/usr/local/apache-tomcat-9.0.62/webapps/test -v /home/chen/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.62/logs diytomcat