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"
            }
        ],
	...

这样的话我们就完成了数据的同步。

测试一下来看:

  1. 将容器停止
  2. 在testDir中新建文件
  3. 启动容器
  4. 容器内数据依旧是同步的

使用容器卷的好处:

在修改文件时,只需要修改本地文件即可,容器会自动同步指定目录下的文件。

实战:安装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

测试是否运行成功:

  1. 可以看mysql目录下是否有data、conf文件夹,如果有则运行成功。
  2. 利用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镜像的文件,一个命令参数脚本。

构建步骤:

  1. 编写一个 dockerfile 文件
  2. docker build构建为一个镜像
  3. docker run运行镜像
  4. docker push发布镜像

DockerFile 构建过程

基础知识

  1. 每个保留关键字(指令)都是大写字母
  2. 从上往下依次执行
  3. # 表示注释
  4. 每一个指令都会创建提交一个新的镜像层,并提交

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           # 构建的时候设置环境变量

docker k8s 出现退出容器 重启 docker容器退出后数据会丢失_linux

实战测试

制作升级版的 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镜像

  1. 准备镜像文件 tomcat 压缩包,jdk的压缩包。
  2. 编写 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
  1. 利用Dockerfile构建镜像:
docker build -t diytomcat
  1. 运行镜像
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. 发布项目:
    (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,显示如下页面

docker k8s 出现退出容器 重启 docker容器退出后数据会丢失_linux_02

(4)成功!

发布自己的 Docker 镜像

发布到Docker Hub官方镜像中

  1. 先去地址 https://hub.docker.com/ 注册账号
  2. 在服务器上发布自己的镜像
# 先登录 docker 账号
docker login
# 系统提示输入 Username 和 password

# 开始push自己的镜像,必须遵循如下格式,否则会被拒绝
docker push <自己的用户名>/<镜像名>:[tag]
  1. 完成!测试一下可以不可以pull自己的镜像:
# nice!
docker pull <自己的用户名>/<镜像名>:[tag]

小结

docker k8s 出现退出容器 重启 docker容器退出后数据会丢失_tomcat_03