📚 DOCKER 容器数据卷
介绍
将运用与运行的环境打包形成容器运行,运行可以伴随着容器,都是我们对数据的要求并没有保存下来,我们希望的是将数据也进行持久化、容器之间有可能共享数据
类似与 redis中的持久化(RDB、AOF)
功能
docker 容器中的修改可以使用 docker commit
进行重新打包,而数据在删除容器后,就没有了,为了能保存数据所以使用docker数据卷
- 数据共享
- 数据持久化
数据卷
docker run -it -v </宿主机绝对路径>:</容器内目录> 镜像名称
:挂载数据卷启动容器
docker run -it -v </宿主机绝对路径>:</容器内目录>:ro 镜像名称
- ro:表示在容器中,只能读取宿主机目录中的内容,无法修改
最佳实践
- 启动容器
docker run -d -p 3306:3306 \
-v /opt/dataVolume/mysql/conf:/etc/mysql/conf.d \
-v /opt/dataVolume/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name mysql mysql-duanyu:5.7
宿主机绝对路径使用自己定义存放数据的位置,然后对应 mysql中数据重复位置
-
查看是否挂载成功
docker inspect [选项] <容器名|容器ID>
:获取容器/镜像元数据
在容器mysql中创建数据库并建表,可以看到挂载的文件中同时出现了对应文件
-
删除容器再次启动容器
docker rm -f $(docker -a -q)
进入容器查看数据是否存在
docker exec -it mysql /bin/bash
初识 DOCKER FILE
- 它类似于一个Java的源文件(.class)只不过它有着一套属于自己的编程语法(docker编程)
FROM openjdk:8-jdk-slim-buster
ENV CATALINA_HOME /usr/local/tomcat
ENV PATH $CATALINA_HOME/bin:$PATH
RUN mkdir -p "$CATALINA_HOME"
WORKDIR $CATALINA_HOME
# let "Tomcat Native" live somewhere isolated
ENV TOMCAT_NATIVE_LIBDIR $CATALINA_HOME/native-jni-lib
ENV LD_LIBRARY_PATH ${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOMCAT_NATIVE_LIBDIR
# see https://www.apache.org/dist/tomcat/tomcat-$TOMCAT_MAJOR/KEYS
# see also "update.sh" (https://github.com/docker-library/tomcat/blob/master/update.sh)
ENV GPG_KEYS 05AB33110949707C93A279E3D3EFE6B686867BA6 07E48665A34DCAFAE522E5E6266191C37C037D42 47309207D818FFD8DCD3F83F1931D684307A10A5 541FBE7D8F78B25E055DDEE13C370389288584E7 5C3C5F3E314C866292F359A8F3AD5C94A67F707E 61B832AC2F1C5A90F0F9B00A1C506407564C17A3 765908099ACF92702C7D949BFA0C35EA8AA299F1 79F7026C690BAA50B92CD8B66A3AD3F4F22C4FED 8B46CA49EF4837B8C7F292DAA54AD08EA7A0233C 9BA44C2621385CB966EBA586F72C284D731FABEE A27677289986DB50844682F8ACB77FC2E86E29AC A9C5DF4D22E99998D9875A5110C01C5A2F6059E7 DCFD35E0BF8CA7344752DE8B6FB21E8933C60243 F3A04C595DB5B6A5F1ECA43E3B7BBB100D811BBE F7DA48BB64BCB84ECBA7EE6935CD23C10D498E23
ENV TOMCAT_MAJOR 8
ENV TOMCAT_VERSION 8.5.69
ENV TOMCAT_SHA512 3ce092c7b89a12904681f23c9c8a2517c13305b4beb783f7b1e85e947aaba4d2bfe8f954f9cefbe009f678557eeb552995f214d9e98c3f1be395822eb2582a1c
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
gnupg dirmngr \
wget ca-certificates \
; \
\
ddist() { \
local f="$1"; shift; \
local distFile="$1"; shift; \
local mvnFile="${1:-}"; \
local success=; \
local distUrl=; \
for distUrl in \
# https://issues.apache.org/jira/browse/INFRA-8753?focusedCommentId=14735394#comment-14735394
"https://www.apache.org/dyn/closer.cgi?action=download&filename=$distFile" \
# if the version is outdated (or we're grabbing the .asc file), we might have to pull from the dist/archive :/
"https://www-us.apache.org/dist/$distFile" \
"https://www.apache.org/dist/$distFile" \
"https://archive.apache.org/dist/$distFile" \
# if all else fails, let's try Maven (https://www.mail-archive.com/users@tomcat.apache.org/msg134940.html; https://mvnrepository.com/artifact/org.apache.tomcat/tomcat; https://repo1.maven.org/maven2/org/apache/tomcat/tomcat/)
${mvnFile:+"https://repo1.maven.org/maven2/org/apache/tomcat/tomcat/$mvnFile"} \
; do \
if wget -O "$f" "$distUrl" --progress=dot:giga && [ -s "$f" ]; then \
success=1; \
break; \
fi; \
done; \
[ -n "$success" ]; \
}; \
\
ddist 'tomcat.tar.gz' "tomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz" "$TOMCAT_VERSION/tomcat-$TOMCAT_VERSION.tar.gz"; \
echo "$TOMCAT_SHA512 *tomcat.tar.gz" | sha512sum --strict --check -; \
ddist 'tomcat.tar.gz.asc' "tomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz.asc" "$TOMCAT_VERSION/tomcat-$TOMCAT_VERSION.tar.gz.asc"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify tomcat.tar.gz.asc tomcat.tar.gz; \
tar -xf tomcat.tar.gz --strip-components=1; \
rm bin/*.bat; \
rm tomcat.tar.gz*; \
command -v gpgconf && gpgconf --kill all || :; \
rm -rf "$GNUPGHOME"; \
\
# https://tomcat.apache.org/tomcat-9.0-doc/security-howto.html#Default_web_applications
mv webapps webapps.dist; \
mkdir webapps; \
# we don't delete them completely because they're frankly a pain to get back for users who do want them, and they're generally tiny (~7MB)
\
nativeBuildDir="$(mktemp -d)"; \
tar -xf bin/tomcat-native.tar.gz -C "$nativeBuildDir" --strip-components=1; \
apt-get install -y --no-install-recommends \
dpkg-dev \
gcc \
libapr1-dev \
libssl-dev \
make \
; \
( \
export CATALINA_HOME="$PWD"; \
cd "$nativeBuildDir/native"; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
aprConfig="$(command -v apr-1-config)"; \
./configure \
--build="$gnuArch" \
--libdir="$TOMCAT_NATIVE_LIBDIR" \
--prefix="$CATALINA_HOME" \
--with-apr="$aprConfig" \
--with-java-home="$JAVA_HOME" \
--with-ssl=yes; \
make -j "$(nproc)"; \
make install; \
); \
rm -rf "$nativeBuildDir"; \
rm bin/tomcat-native.tar.gz; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \
find "$TOMCAT_NATIVE_LIBDIR" -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { print $(NF-1) }' \
| xargs -rt readlink -e \
| sort -u \
| xargs -rt dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
rm -rf /var/lib/apt/lists/*; \
\
# sh removes env vars it doesn't support (ones with periods)
# https://github.com/docker-library/tomcat/issues/77
find ./bin/ -name '*.sh' -exec sed -ri 's|^#!/bin/sh$|#!/usr/bin/env bash|' '{}' +; \
\
# fix permissions (especially for running as non-root)
# https://github.com/docker-library/tomcat/issues/35
chmod -R +rX .; \
chmod 777 logs temp work; \
\
# smoke test
catalina.sh version
# verify Tomcat Native is working properly
RUN set -eux; \
nativeLines="$(catalina.sh configtest 2>&1)"; \
nativeLines="$(echo "$nativeLines" | grep 'Apache Tomcat Native')"; \
nativeLines="$(echo "$nativeLines" | sort -u)"; \
if ! echo "$nativeLines" | grep -E 'INFO: Loaded( APR based)? Apache Tomcat Native library' >&2; then \
echo >&2 "$nativeLines"; \
exit 1; \
fi
EXPOSE 8080
CMD ["catalina.sh", "run"]
-
编写一个简单的Dockerfile
新建一个Dockerfile文件在文件中编写
FROM docker.io/centos
VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
CMD echo "this is duanyu writed Docker File"
CMD /bin/bash
-
构建镜像
docker build -f <Dockerfile 文件路径> -t <镜像名称>
构建完成后查看镜像文件docker images
-
run
docker run -it <镜像ID>
启动后,可以发现自带就有2个我们自己定义的容器卷文件夹
但是我们并没有指定挂载在宿主机那个位置,docker 会默认为我们生成一个挂载位置,并且默认可读可写
数据卷容器
有一块虚拟的公共空间,里面的数据对于不同的容器以及部署docker容器的应用服务器,他们可以通过这块空间进行数据传递,从而实现数据共享,但是这个公共区域是一个虚拟的概念,真正运用的时候,其实是服务器上的某一个具体的目录到容器上某一个目录的空间映射
- 起一个容器使其他容器继承这个容器
[root@localhost /]# docker run -it --name centos01 centos-duanyu
[root@e21485c12f8c /]# [root@localhost /]#
[root@localhost /]# docker run -it --name centos02 --volumes-from centos01 centos-duanyu
[root@cafd3b65c735 /]# [root@localhost /]#
[root@localhost /]# docker run -it --name centos03 --volumes-from centos02 centos-duanyu
[root@7c4d0cb34d90 /]#
- 在 centos03容器中创建hello文件我们再进入到centos02 和centos01 容器中发现数据确实是共享的
- 我们在centos01容器中再创建一个test文件并删除centos01容器
- 再次进入centos02或03
可以发现centos01在没删除之前创建的文件,而即使删除了容器,我们的数据依然存在
只要有一个容器存在,我们的共享数据文件生命周期就不会失效
DOCKER FILE 解析
话不多说,先上图片!有个大概了解,再深入操作
构建过程解析
-
Dockerfile内容基础知识
每条保留字指令都必须为大写字母,且后面至少跟随一个参数
指令按照从上到下,顺序执行
“#” 表示注释
每条指令都会创建一个新的镜像层,并对镜像进行提交
-
Docker执行 Dockerfile大致流程
1.docker从基础镜像运行一个容器
2.执行一条指令并对容器作出修改
3.执行类似docker commit的操作提交一个新的镜像层
4.docker再基于刚刚提交的镜像运行一个新容器
5.执行dockerfile中下一条指令重复以上操作,直到所有指令全部执行完毕
体系结构
保留字指令 | 简介 | 示例 |
---|---|---|
FROM | 基础镜像,当前新镜像是基于哪个镜像的 | FROM scratch |
MAINTAINER | 镜像维护者的姓名和邮箱地址信息 | MAINTAINER https://github.com/Z-Kanan/ |
RUN | 容器构建时需要运行的命令 | RUN groupadd -r redis && useradd -r -g redis |
EXPOSE | 当前容器对外暴露出的端口号 | EXPOSE 3306 |
WORKDIR | 指定在创建容器后,终端默认登陆进来的工作目录,一个落脚点 | WORKDIR /data、WORKDIR $MY_PATH |
ENV | 用来在构建镜像过程中设置环境变量 | ENV MY_PATH/usr/test |
COPY | 拷贝文件和目录到镜像中,将从构建上下文目录中<源路径>的文件/目录复制到新的一层的镜像内的<目录路径>位置 | COPY /centos-6-docker.tar.xz / |
ADD | 类似COPY 将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包 | ADD centos-6-docker.tar.xz / |
VOLUME | 容器数据卷,用于数据保存和持久化工作 | VOLUME ["/volume1","/volume2"] |
CMD | 指定一个容器启动时要运行的命令(Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换) | CMD ["/bin/bash"] |
ENTRYPOINT | 指定一个容器启动时要运行的命令(和CMD一样,都是在指定容器启动程序及参数,它会被dockerrun之后的参数追加) | ENTRYPOINT ["/bin/bash"] |
ONBULID | 当构建一被继承的Dockerfile时运行命令,父镜像在被子镜像的onbuild触发 | |
LABEL | 标签,描述 | name=“CentOS Base Image” version= “1.0” |
最佳实践
-
Base镜像(scratch):Docker Hub 中大多数的镜像都是通过在base镜像中安装和配置需要的软件而构建出的
编写Duockerfile
-
场景:在我们起一个centos容器或mysql容器时,它里面并没有一些常用的命令如:vim、ifconfig等,所以我希望我的镜像启动时就自带这些命令
-
编写文件:如果在当前路径下文件名为标准Dockerfile 构建时无需指定-f
#依赖镜像 FROM docker.io/centos #作者吗名称邮箱 MAINTAINER duanyu<DuanyuCode@gmail.com> #启动落脚点 #定义环境变量 ENV MY_PATH /opt/ #使用环境变量指定落脚点 WORKDIR $MY_PATH #需要运行的命令 #安装需要的指令 RUN yum -y install vim RUN yum -y install net-tools #对外暴露的端口号 EXPOSE 80 #启动容器时需要运行的命令 CMD /bin/bash
-
构建镜像:
docker build -f /opt/mydocker/Dockerfile2 -t centos-duanyu:1.1 .
表示构建成功,且镜像ID这个打印的ID
-
启动镜像:
docker run -it --name centos01 centos-duanyu:1.1
可以看到落脚点就是我们在dockerfile 中指定的落脚点
vim -v
:查看vim版本信息ifconfig
:查看ip消息都可以成功操作
CMD 替换理解
-
当我们启动tomcat容器时,默认就启动了tomcat服务器,是因为在dockerfile中最后一行写了 CMD [“catalina.sh”,“run”](json写法)
-
如果我们在启动时使用
docker run -it -p 8080:8080 tomcat ls -l
等于启动后执行ls -l 指令,把启动tomcat服务指令给替换了可以看到打印出了 /usr/local/tomcat路径下的所有文件展示而并没有启动tomcat服务
ENTRYPOINT 追加理解
-
在docker hub 上找一个tomcat的dockerfile 文件内容,将最后的CMD 改为ENTRYPOINT
FROM centos-duanyu:1.1 ENTRYPOINT ["echo","hello!!!"]
-
重新构建tomcat镜像
docker build -f <dockerfile 路径> -t <镜像名称:版本> .
-
运行镜像容器
可以看是追加输出的
ONBULID 理解
-
在dockerfile文件中编写一个 ONBUILD 内容
FROM centos-duanyu:1.1 ENTRYPOINT ["echo","hello!!!"] ONBUILD RUN echo "centos-duanyu-1.2 被依赖"
-
重新构建当前镜像
-
再编写一个dockerfile 依赖于这个镜像
FROM centos1.3 CMD /bin/bash
-
构建
当我们构建时,就可以看到这行红色的提示,说明ONBUILD被触发了
构建TOMCAT镜像
-
构建前提
-
编写dockerfile
#依赖的镜像 FROM centos #作者信息 MAINTAINER duanyu<duanyucode@gmail.com> #把java和tomcat添加添加到容器中 ADD jdk-8u301-linux-x64.tar.gz /usr/local ADD apache-tomcat-9.0.50.tar.gz /usr/local #安装vim编辑器 RUN yum -y install vim #设置工作访问时的登录落脚点 ENV MY_PATH /usr/local WORKDIR $MY_PATH #配置java与tomcat环境变量 ENV JAVA_HOME /usr/local/jdk1.8.0_301 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.50 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA/lib:$CATALINA_HOME/bin #容器运行时监听的端口 EXPOSE 8080 #启动容器时执行的命令 CMD /usr/local/apache-tomcat-9.0.50/bin/startup.sh \ && tail -F /usr/local/apache-9.0.50/bin/logs/catalina.out
-
构建镜像得到一个tomcat镜像
当我们的dockerfile名为标准名称时(Dockerfile)docker会自动识别文件,在本路径下构建无需指定 -f
docker build -t tomcat9-duanyu .
-
使用挂载容器卷启动
docker run -d -p 8899:8080 --name tmocat01 \ -v /opt/dataVolume/tomcat01/test:/usr/local/apache-tomcat-9.0.50/webapps/test \ -v /opt/dataVolume/tomcat01/tomcat01logs/:/usr/local/apache-tomcat-9.0.50/logs \ --privileged=true tomcat9-duanyu
我们进入到挂载的共享文件夹中添加一个hello文件
查看容器中的文件
-
访问服务器
同理,我们可以将web程序直接丢到文件中,即可以访问服务
安装 Redis
-
docker pull redis
:下载一个redis镜像 -
启动容器
docker run -p 6379:6379 --name redis01 \ -v /opt/dataVolume/redis01/data:/data \ -v /opt/dataVolume/redis01/conf/redis.conf:/usr/local/etc/redis/redis.conf \ -d redis redis-server /usr/local/etc/redis/redis.conf --appendonly yes
-
在宿主机 /opt/dataVolume/redis01/conf/redis.conf/ 添加一个redis.conf配置文件即为redis的配置文件
推送镜像到阿里云
在使用Docker时,有时需要制作自己的Docker镜像,这些镜像可以保存到不同的Docker Hub中,包括Docker官方的和国内的一些Hub,比如阿里云。同时,也可以使用阿里云的Docker Hub来加速镜像的拉取速度。
-
登录阿里云,进入容器镜像服务
-
创建个人实例访问凭证
-
创建命名空间
-
创建仓库选择本地仓库
根据操作指南进行推送