Docker 学习笔记(3)
容器数据卷
什么是容器数据卷
如果数据都在容器中,那么我们将容器删除,数据就会丢失。需求:数据可以持久化
MySql,容器被删除数据就全都没了。需求:将MySql数据存储在本地
我们需要做的就是将我们容器内的目录挂在到Linux上!
一句话:容器的持久化和同步操作,容器间的数据也可以共享!
使用容器数据卷
docker run -it -v 主机目录:容器内目录
# 实战测试
docker run -it -v /home/testDir:/home centos /bin/bash
# 此时我们已经进入到centos中
cd /home # 进入容器内的home目录
touch test.txt # 创建文件
ctrl+p+q # 退出该容器
cd /home/testDir # 进入主机的目录
ls # 查看该目录文件
# 显示如下
[root@GengCloud home]# cd testDir/
[root@GengCloud testDir]# ls
test.txt
我们也可以利用docker inspect
命令查看挂载目录:
docker inspect CONTAINER # 查看元数据,显示挂载信息如下
...
"Mounts": [
{
"Type": "bind",
"Source": "/home/testDir", # 主机内地址
"Destination": "/home", # docker容器内地址
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
...
这样的话我们就完成了数据的同步。
测试一下来看:
- 将容器停止
- 在testDir中新建文件
- 启动容器
- 容器内数据依旧是同步的
使用容器卷的好处:
在修改文件时,只需要修改本地文件即可,容器会自动同步指定目录下的文件。
实战:安装MySql
# 获取镜像
docker pull mysql
# 运行容器并挂载
docker run -dp 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql
# 官方测试命令如下
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
测试是否运行成功:
- 可以看mysql目录下是否有data、conf文件夹,如果有则运行成功。
- 利用Workbench(Sqlyog、Navicat等)连接ip:3306,正常情况下测试是连接成功的。
将容器删除后,本地文件依旧存在,说明数据已经持久化。
具名和匿名挂载
# 匿名挂载
-v 容器内路径
docker run -d -P --name nginx01 -v /ect/nginx nginx
# 查看所有的 volume 情况
docker volume ls
# 显示如下,发现 -v 只写了容器内路径,没写容器外路径
DRIVER VOLUME NAME
local 8f3a4849ddaed86649556914d2b3733f...
# 具名挂载
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
docker volume ls
# 显示如下
DRIVER VOLUME NAME
local juming-nginx
# 查看卷详细信息
docker volume inspect juming-nginx
#显示如下
[
{
"CreatedAt": "2021-12-12T15:34:37+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data",
"Name": "juming-nginx",
"Options": null,
"Scope": "local"
}
]
发现当我们没有指定目录的情况下,卷的位置在 /var/lib/docker/volumes/**/_data
下。
通过具名挂载可以方便地找到卷,大多数情况在使用的具名挂载。
# 如何确定具名挂在还是匿名挂载
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /宿主机路径:容器内路径 # 指定路径挂载
拓展:
# 通过 -v 容器内路径:ro rw 改变读写权限
ro read only # 路径只能通过宿主机修改
rw read write
# 权限是指这个目录对容器的限制
# 一旦设置容器权限,容器对挂载的内容就被限定了
docker run -d -P --name nginx02 -v juming-nginx:/ext/nginx:ro nginx
初识 Dockerfile
Dockerfile 就是用来构建 docker 镜像的构建文件,命令脚本。
可以通过这个脚本,一个一个的命令,每个命令都是一层。
# vim dockerfile
# 这里采用的是匿名挂载
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "-----end-----"
CMD /bin/bash
然后利用这个 dockerfile
来构建新的镜像:
# 执行如下命令
docker build -f dockerfile -t mycentos
# 显示如下
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM centos
---> 5d0da3dc9764
Step 2/4 : VOLUME ["volume01","volume02"]
---> Running in 1a6292c4e16a
Removing intermediate container 1a6292c4e16a
---> 0e806d320a83
Step 3/4 : CMD echo "-----end-----"
---> Running in f779110d3b02
Removing intermediate container f779110d3b02
---> adc376ac1053
Step 4/4 : CMD /bin/bash
---> Running in 59064f9cf95d
Removing intermediate container 59064f9cf95d
---> 1ebd472c09db
# 查看挂载信息
docker inspect CONTAINER
# 显示如下
...
"Mounts": [
{
"Type": "volume",
"Name": "9e2ee53f959f2faac1782dfbec8353d862dd63d86d75d3f483539d62fe862daf",
"Source": "/var/lib/docker/volumes/9e2ee53f959f2faac1782dfbec8353d862dd63d86d75d3f483539d62fe862daf/_data",
"Destination": "volume01",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "72353798aa4954f257c8fdd65068dedea1593b2110f3a6de1122ed4aafa42581",
"Source": "/var/lib/docker/volumes/72353798aa4954f257c8fdd65068dedea1593b2110f3a6de1122ed4aafa42581/_data",
"Destination": "volume02",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
...
数据卷容器
容器间的数据共享实现:
# 启动两个容器,利用刚才建立的 dockerfile
docker run -it --name docker01 mycentos
# docker02 挂载 docker01 的数据卷容器
docker run -it --name docker02 --volumes-from docker01 mycentos
此时如果移除docker01那么docker02的数据会不会消失呢?
答案:不会,不要忘了我们的docker01已经通过匿名挂载挂载到宿主机了,就算docker01消失,数据也不会消失。
结论: 容器间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用位置。但是一旦持久化到了本地,本地的数据是不会删除的。
DockerFile
dockerfile 是用来构建docker镜像的文件,一个命令参数脚本。
构建步骤:
- 编写一个
dockerfile
文件 -
docker build
构建为一个镜像 -
docker run
运行镜像 -
docker push
发布镜像
DockerFile 构建过程
基础知识
- 每个保留关键字(指令)都是大写字母
- 从上往下依次执行
- # 表示注释
- 每一个指令都会创建提交一个新的镜像层,并提交
dockerfile 是面向开发的,以后发布项目,做镜像都要编写dockerfile文件,逐渐成为企业交付的标准。
DockerFile:构建文件,定义了一切的步骤,源代码。
DockerImages:通过DockerFile构建生成的镜像,最终发布和运行产品。
Docker容器:就是镜像运行起来提供服务器。
DockerFile 的指令
FROM # 基础镜像,从这里开始构建
MAINTAINER # 镜像作者,姓名+邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 在基础镜像中添加内容
WORKDIR # 镜像的工作目录
VOLUME # 设置容器卷,挂载的目录位置
EXPOSE # 指定暴露端口!EXPOSE 在DockerFile中只是声明端口,还是要run的时候使用-p的
RUN # 容器打开后需要运行的
CMD # 指定容器启动时要运行的命令,只有最后一个会生效,会被替代
ENTRYPOINT # 与CMD类似,可以追加命令
ONBUILD # 当构建一个被继承 DockerFile 的时候,就会运行 ONBUILD 指令,触发指令
COPY # 类似ADD,将文件拷贝到镜像中
ENV # 构建的时候设置环境变量
实战测试
制作升级版的 centos
Docker Hub 中 99% 的镜像都是从这个基础镜像构建的FROM scratch
,然后配置需要的软件和配置来进行的构建。
# centos8的 DockerFile 如下:
FROM scratch
ADD centos-8-x86_64.tar.xz /
LABEL org.label-schema.schema-version="1.0"\
org.label-schema.name="CentOS Base Image"\
org.label-schema.vendor="CentOS"\
org.label-schema.license="GPLv2"\
org.label-schema.build-date="20210915"
CMD ["/bin/bash"]
创建一个自己的 Centos
# 编写自己的DockerFile
vim myDockerFile
FROM centos
MAINTAINER geng<1161906117@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指令替代了
CMD /bin/bash
执行如下命令,来构建镜像:
# 构建命令
docker build -f myDockerFile -t mycentos:0.1 .
# 显示如下
....
Successfully built be779832c8c7
Successfully tagged mycentos:0.1
# 测试运行
docekr run -it mycentos:0.1
可以利用docker history IMAGE
指令查看构建历史:
docker history mycentos:0.1
#显示如下
[root@GengCloud dockerfile]# docker history mycentos:0.1
IMAGE CREATED CREATED BY SIZE
be779832c8c7 6 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B
877708e7d88e 6 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
ed1a6faf86db 6 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
3d14a264c22f 6 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B
e5872a9ce471 6 minutes ago /bin/sh -c yum -y install net-tools 27MB
5752a150c14f 6 minutes ago /bin/sh -c yum -y install vim 64MB
2bc0bce095fe 7 minutes ago /bin/sh -c #(nop) WORKDIR /usr/local 0B
c187da78b8ec 7 minutes ago /bin/sh -c #(nop) ENV MYPATH=/usr/local 0B
040bc3673549 7 minutes ago /bin/sh -c #(nop) MAINTAINER geng<116190611… 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
DockerFile 制作Tomcat镜像
- 准备镜像文件 tomcat 压缩包,jdk的压缩包。
- 编写 Dockerfile文件
# 编写新的Dockerfile
vim Dockerfile
FROM centos
MAINTAINER geng<1161906117@qq.com>
COPY readme.txt /usr/local/readme.txt
# 这一步会自动解压
ADD jdk-8u311-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.56.tar.gz /usr/local/
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR ${MYPATH}
ENV JAVA_HOME /usr/local/jdk1.8.0_311 # 目录不要搞错了
ENV CLASSPATH ${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.56
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.56
ENV PATH ${PATH}:${JAVA_HOME}/bin:${CATALINA_HOME}/lib:${CATALINA_HOME}/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.56/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.56/bin/logs/catalina.out
- 利用Dockerfile构建镜像:
docker build -t diytomcat
- 运行镜像
docker run -dp 9090:8080 --name gengtomcat -v /home/geng/build/tomcat/test:/usr/local/apache-tomcat-9.0.56/webapps/test -v /home/geng/build/tomcat/tomcatlogs:/usr/local/apache-tomcat-9.0.56/logs diytomcat
# 测试是否成功,注意要在容器外执行
curl localhost:9090
# 显示如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Apache Tomcat/9.0.56</title>
<link href="favicon.ico" rel="icon" type="image/x-icon" />
<link href="tomcat.css" rel="stylesheet" type="text/css" />
</head>
...
- 发布项目:
(1)在test目录下建立WEB-INF
目录和web.xml文件
cd /home/geng/build/tomcat/test
mkdir WEB-INF
cd WEB-INF
vim web.xml
# 输入web.xml文件内容
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.org/xml/ns/javaee
http://java.sun.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
</web-app>
(2)在test目录下建立index.jsp文件
cd .. # test 目录
vim index.jsp
# 输入index.jsp文件内容
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>geng</title>
</head>
<body>
hello world! <br/>
<%
System.out.println("hello geng");
%>
</body>
</html>
(3)打开浏览器并输入 ip:9090/test,显示如下页面
(4)成功!
发布自己的 Docker 镜像
发布到Docker Hub官方镜像中
- 先去地址 https://hub.docker.com/ 注册账号
- 在服务器上发布自己的镜像
# 先登录 docker 账号
docker login
# 系统提示输入 Username 和 password
# 开始push自己的镜像,必须遵循如下格式,否则会被拒绝
docker push <自己的用户名>/<镜像名>:[tag]
- 完成!测试一下可以不可以pull自己的镜像:
# nice!
docker pull <自己的用户名>/<镜像名>:[tag]
小结