二: Docker 镜像与制作
Docker 镜像有没有内核?
从镜像大小上面来说,一个比较小的镜像只有十几 MB,而内核文件需要一百多兆, 因此镜像里面是没有内核的, 镜像在被启动为容器后将直接使用宿主机的内核, 而镜像本身则只提供相应的 rootfs, 即系统正常运行所必须的用户空间的文件系统,比如/dev/, /proc, /bin, /etc 等目录, 所以容器当中基本是没有/boot目录的,而/boot 当中保存的就是与内核相关的文件和目录
为什么没有内核?
由于容器启动和运行过程中是直接使用了宿主机的内核,所以没有直接调用过物理硬件, 所以也不会涉及到硬件驱动, 因此也用不上内核和驱动,另外有内核的那是虚拟机。
2.1: 手动制作 yum 版 nginx 镜像
Docker 制作类似于虚拟机的模板制作,即按照公司的实际业务务求将需要安装的软件、相关配置等基础环境配置完成,然后将虚拟机再提交为模板,最后再批量从模板批量创建新的虚拟机,这样可以极大的简化业务中相同环境的虚拟机运行环境的部署工作, Docker 的镜像制作分为手动制作和自动制作 (基于DockerFile), 企业通常都是基于 Dockerfile 制作镜像, 其中手动制作镜像步骤具体如下:
2.1.1: 下载镜像并初始化系统
基于某个基础镜像之上重新制作, 因此需要先有一个基础镜像,本次使用官方提供的 centos 镜像为基础
[root@docker-server1 ~]# docker pull centos
[root@docker-server1 ~]# docker run -it docker.io/centos /bin/bash
[root@37220e5c8410 /]# yum install wget -y
[root@37220e5c8410 /]# cd /etc/yum.repos.d/
[root@37220e5c8410 yum.repos.d]# rm -rf ./* #更改 yum 源
[root@37220e5c8410 yum.repos.d]# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
[root@37220e5c8410 yum.repos.d]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
2.1.2: yum 安装并配置 nginx
[root@37220e5c8410 yum.repos.d]# yum install nginx –y #yum 安装 nginx
[root@37220e5c8410 yum.repos.d]# yum install -y vim wget pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop #安装常用命令
2.1.3: 关闭 nginx 后台运行
[root@37220e5c8410 yum.repos.d]# vim /etc/nginx/nginx.conf #关闭 nginx 后台运行
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
daemon off; #关闭后台运行
2.1.4:自定义 web 页面
[root@37220e5c8410 yum.repos.d]# vim /usr/share/nginx/html/index.html
[root@37220e5c8410 yum.repos.d]# cat /usr/share/nginx/html/index.html
Docker Yum Nginx #自定义 web 界面
2.1.5: 提交为镜像
在宿主机基于容器 ID 提交为镜像
root@docker-node1:~# docker commit --help
Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
Create a new image from a container's changes
Options:
-a, --author string Author (e.g., "John Hannibal Smith ")
-c, --change list Apply Dockerfile instruction to the created image
-m, --message string Commit message
-p, --pause Pause container during commit (default true)
[root@docker-server1 ~]# docker commit -a "[email protected]" -m "nginx yum v1" --change="EXPOSE 80 443" f5f8c13d0f9f centos-nginx:v1
sha256:7680544414220f6ff01e58ffc6bd59ff626af5dbbce4914ceb18e20f4ae0276a
#小笔记:
docker commit -a "[email protected]" -m "yum install nginx -y" -c 'CMD ["/usr/sbin/nginx"]' --change="EXPOSE 80 443" f5f8c13d0f9f centos:latest
2.1.6: 带 tag 的镜像提交
提交的时候标记 tag 号:
#标记 tag 号,生产当中比较常用,后期可以根据 tag 标记创建不同版本的镜像以及创建不同版本的容器。
[root@docker-server1 ~]# docker commit -m "nginx image" f5f8c13d0f9f jack/centos-nginx:v1
sha256:ab9759679eb586f06e315971d28b88f0cd3e0895d2e162524ee21786b98b24e8
2.1.7: 从自己镜像启动容器
[root@docker-server1 ~]# docker run -d -p 80:80 --name my-centos-nginx jack/centos-nginx /usr/sbin/nginx
ce4ee8732a0c4c6a10b85f5463396b27ba3ed120b27f2f19670fdff3bf5cdb62
2.1.8: 访问测试
http://ip
2.2: DockerFile 制作编译版 nginx 1.16.1 镜像
DockerFile 可以说是一种可以被 Docker 程序解释的脚本, DockerFile 是由一条条的命令组成的,每条命令对应 linux 下面的一条命令, Docker 程序将这些 DockerFile 指令再翻译成真正的 linux 命令,其有自己的书写方式和支持的命令, Docker 程序读取 DockerFile 并根据指令生成 Docker 镜像,相比手动制作镜像的方式, DockerFile 更能直观的展示镜像是怎么产生的,有了写好的各种各样 DockerFile 文件,当后期某个镜像有额外的需求时,只要在之前的DockerFile 添加或者修改相应的操作即可重新生成新的 Docke 镜像,避免了重复手动制作镜像的麻烦,具体如下:
https://docs.docker.com/engine/reference/builder/
ADD
COPY
ENV
EXPOSE
FROM
LABEL
STOPSIGNAL
USER
VOLUME
WORKDIR
RUN
2.2.1:下载镜像并初始化系统
[root@docker-server1 ~]# docker pull centos
[root@docker-server1 ~]# docker run -it docker.io/centos /bin/bash
[root@docker-server1 ~]# cd /opt/ #创建目录环境
[root@docker-server1 opt]# mkdir dockerfile/{web/{nginx,tomcat,jdk,apache},system/{centos,ubuntu,redhat}} -pv
#目录结构按照业务类型或系统类型等方式划分,方便后期镜像比较多的时候进行分类。
进入到指定的 Dockerfile 目录
[root@docker-server1 opt]# cd dockerfile/web/nginx/
[root@docker-server1 nginx]# pwd
/opt/dockerfile/web/nginx
2.2.2: 编写 Dockerfile
[root@docker-server1 nginx]# vim ./Dockerfile #生成的镜像的时候会在执行命令的当前目录查找 Dockerfile 文件, 所以名称不可写错, 而且 D 必须大写
#My Dockerfile
#"#"为注释,等于 shell 脚本的中#
#除了注释行之外的第一行,必须是 From xxx (xxx 是基础镜像)
From centos #第一行先定义基础镜像,后面的本地有效的镜像名,如果本地没有会从远程仓库下载,第一行很重要
#镜像维护者的信息
MAINTAINER Jack.Zhang [email protected]
###########################其他可选参数
##################################################
#USER #指定该容器运行时的用户名和 UID,后续的 RUN 命令也会使用这面指定的用户执行
#WORKDIR /a
#WORKDIR b #指定工作目录,最终为/a/b
#VOLUME ["/dir_1", "/dir_2" ..] 设置容器挂载主机目录
#ENV name jack #设置容器变量,常用于想容器内传递用户密码等
#####################################################################
####################
#执行的命令,将编译安装 nginx 的步骤执行一遍
RUN rpm -ivh http://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm
RUN yum install -y vim wget tree lrzsz gcc gcc-c++ automake pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop
ADD nginx-1.16.1.tar.gz /usr/local/src/ #自动解压压缩包
RUN cd /usr/local/src/nginx-1.16.1 && ./configure --prefix=/usr/local/nginx --
with-http_sub_module && make && make install
RUN cd /usr/local/nginx/
ADD nginx.conf /usr/local/nginx/conf/nginx.conf
RUN useradd nginx -s /sbin/nologin
RUN ln -sv /usr/local/nginx/sbin/nginx /usr/sbin/nginx
RUN echo "test nginx page" > /usr/local/nginx/html/index.html
EXPOSE 80 443 #向外开放的端口,多个端口用空格做间隔,启动容器时候-p需要使用此端向外映射,如: -p 8081:80,则 80 就是这里的 80
CMD ["nginx","-g","daemon off;"] #运行的命令,每个 Dockerfile 只能有一条,如果有多条则只有最后一条被执行
如果在从该镜像启动容器的时候也指定了命令,那么指定的命令会覆盖Dockerfile 构建的镜像里面的 CMD 命令,即指定的命令优先级更高, Dockerfile 的优先级较低一些, 重新指定的指令优先级要高一些。
2.2.3: 准备源码包与配置文件
[root@docker-server1 nginx]# cp /usr/local/nginx/conf/nginx.conf . #使用其它服务器编译安装相同版本的 nginx 配置文件,而且配置文件中关闭 Nginx 进程后台运行
[root@docker-server1 nginx]# cp /usr/local/src/nginx-1.16.1.tar.gz . #nginx 源码包
2.2.4: 执行镜像构建
docker build -t nginx:v1 .
2.2.5: 构建完成
可以清晰看到各个步骤执行的具体操作
2.2.6: 查看是否生成本地镜像
docker images
2.2.7: 从镜像启动容器
root@docker-server1:~# docker run -it -d -p 80:80 nginx:v1
8c48b74c1f86305eef18e8950fb25451c159aeda092902b6d52d6074cb0fe152
2.2.8: 访问 web 界面
http://ip
2.2.9: 镜像编译制作程中
制作镜像过程中,需要启动一个临时的容器进行相应的指令操作,操作完成后再把此容器转换为 image 。
小笔记:Dockerfile
https://docs.docker.com/engine/reference/builder/
Dockerfile命令
FROM #指定父镜像
MAINTAINER #定义镜像作者信息
ADD #添加本地文件到容器,tar包会自动解压
COPY #添加本地文件到容器,需要手动解压
ENV #定义容器环境变量
ENV name mage
ENV age 18
RUN #在容器中执行命令
EXPOSE #定义容器暴露的端口
LABEL #指定生成镜像的元数据标
LABEL MAINTAINER="LiangJC [email protected]"
STOPSIGNAL #指定容器退出的信号值
STOPSIGNAL signal
STOPSIGNAL 9
USER #指定容器执行操作的用户
USER [:]
VOLUME #指定挂载点
VOLUME ["/data/static/linux39","/data/static/magedu","/data/app"]
VOLUME /data/mysql /data/php
WORKDIR #指定工作目录
WORKDIR /path
ENTRYPOINT #跟CMD相似
ENTRYPOINT ["/apps/tomcat/bin/run_tomcat.sh"]
CMD ["nginx","-g","daemon off"]
#例子
mkdir /opt/nginx
cd /opt/nginx-v1
vim Dockerfile
#Nginx web image
from centos:latest
run yun install epel-release -y
run yun install nginx -y
expose 80 443 8080 #容器暴露的端口
CMD ["nginxg","-g","daemon off;"]
docker build -t nginx:v1 .
#例子2:
cd /opt/nginx-v1
vim nginx.conf
daemon off; #全局添加这一行,关闭后台运行
vim Dockerfile
FROM centos #基于什么系统制作
MAINTAINER LiangJC [email protected] #作者信息
RUN yum install epel-release -y && yum install nginx -y && rm -rf /usr/share/nginx/html/* #执行相关命令
#USER #容器以什么身份运行
ADD nginx.conf /etc/nginx/
ADD code.tar.gz /usr/share/nginx/html #添加文件,自动替换
EXPOSE 80 443 #容器暴露的端口
CMD ["nginx"] #执行的命令
docker build -t nginx:v2 .
#脚本自动化
vim build-cmd.sh
#!/bin/bash
docker build -t nginx:$1 .
build-cmd.sh 20200625_160010
2.3: 手动制作编译版本 nginx 1.16.1 镜像
过程为在 centos 基础镜像之上手动编译安装 nginx,然后再提交为镜像。
2.3.1:下载镜像并初始化系统
[root@docker-server1 ~]# docker pull centos
[root@docker-server1 ~]# docker run -it docker.io/centos /bin/bash
[root@86a48908bb97 /]# yum install wget -y
[root@86a48908bb97 /]# cd /etc/yum.repos.d/
[root@86a48908bb97 yum.repos.d]# rm -rf ./* #更改 yum 源
[root@86a48908bb97 yum.repos.d]# wget -O /etc/yum.repos.d/CentOS-Base.repo
http://mirrors.aliyun.com/repo/Centos-7.repo
[root@86a48908bb97 yum.repos.d]# wget -O /etc/yum.repos.d/epel.repo
http://mirrors.aliyun.com/repo/epel-7.repo
2.3.2: 编译安装 nginx
[root@86a48908bb97 yum.repos.d]# yum install -y vim wget tree lrzsz gcc gccc++ automake pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop #安装基础包
[root@86a48908bb97 yum.repos.d]# cd /usr/local/src/
[root@86a48908bb97 src]# wget http://nginx.org/download/nginx-1.16.1.tar.gz
[root@86a48908bb97 src]# tar xvf nginx-1.16.1.tar.gz
[root@86a48908bb97 src]# cd nginx-1.16.1
[root@86a48908bb97 nginx-1.16.1]# ./configure --prefix=/apps/nginx --withhttp_sub_module
[root@86a48908bb97 nginx-1.16.1]# make && make install
[root@86a48908bb97 nginx-1.16.1]# cd /apps/nginx/
2.3.3:关闭 nginx 后台运行
[root@86a48908bb97 nginx]# vim /apps/nginx/conf/nginx.conf
user nginx;
worker_processes auto;
daemon off;
[root@86a48908bb97 nginx]# ln -sv /apps/nginx/sbin/nginx /usr/sbin/nginx #创建 nginx 命令软连
2.3.4: 自定义 web 界面
[root@86a48908bb97 nginx]# mkdir /apps/nginx/html/magedu
[root@86a48908bb97 nginx]# echo "magedu" > /apps/nginx/html/magedu/index.html
2.3.5: 创建用户及授权
[root@86a48908bb97 nginx]# useradd -u 2019 nginx -s /sbin/nologin
[root@86a48908bb97 nginx]# chown nginx.nginx /usr/local/nginx/ -R
2.3.6: 提交为镜像
[root@docker-server1 ~]# docker commit -m "test nginx" 86a48908bb97 magedunginx:v1
sha256:fce6e69410e58b8e508c7ffd2c5ff91e59a1144847613f691fa5e80bb68efbfa
2.3.8: 从自己的镜像启动容器
[root@docker-server1 ~]# docker run -d -p 80:80 --name magedu-centos-nginx magedu-nginx:v1 /usr/sbin/nginx
8042aedec1d6412a79ac226c9289305087fc062b0087955a3a0a609c891e1122
备注: -name 是指定容器的名称, -d 是后台运行, -p 是端口映射, jack/nginx-testimage 是 xx 仓库下的 xx 镜像的 xx 版本,可以不加版本,不加版本默认是使用latest,最后面的 nginx 是运行的命令,即镜像里面要运行一个 nginx 命令,所以才有了前面将/usr/local/nginx/sbin/nginx 软连接到/usr/sbin/nginx,目的就是为了让系统可以执行此命令。
2.3.8: 访问测试
http://ip
2.3.9: 查看 Nginx 访问日志
tail -f /usr/local/nginx/logs/access.log
小笔记:Dockerfile编译安装nginx
cd /opt/nginx-v2
vim nginx.conf
daemon off; #全局添加这一行,关闭后台运行
vim Dockerfile
FROM centos #基于什么系统制作
MAINTAINER LiangJC [email protected] #作者信息
RUN yum install epel-release -y && yum install -y vim lrzsz tree screen psmisc lsof tcpdump wget ntpdate gcc gcc-c++ glibc glibc-devel pcre pcre-devel openssl openssl-devel systemd-devel net-tools iotop bc zip unzip zlib-devel bash-completion nfs-utils automake libxml2 libxml2-devel libxslt libxslt-devel perl perl-ExtUtils-Embed make
#USER #容器以什么身份运行
#ENV MYSQL_HOST 192.168.37.27
ADD nginx-1.16.1.tar.gz /usr/local/src/
RUN cd /usr/local/src/nginx-1.16.1 && ./configure --prefix=/apps/nginx && make && make install
ADD nginx.conf /apps/nginx/conf/
ADD code.tar.gz /apps/nginx/html #添加文件,自动替换
EXPOSE 80 443 #容器暴露的端口
CMD ["/apps/nginx/sbin/nginx"] #执行的命令
cd /opt/nginx-v2
wget https://nginx.org/download/nginx-1.16.1.tar.gz
docker build -t nginx:make .
2.4: 自定义 tomcat 镜像
基于官方提供的 centos、 debain、 ubuntu、 alpine 等基础镜像构建 JDK(Java 环境),然后再基于自定义的 JDK 镜像构建出业务需要的 tomcat 镜像。
2.4.1: 构建 JDK 镜像
先基于官方提供的基础镜像, 制作出安装了常用命令的自定义基础镜像, 然后在基础镜像的基础之上, 再制作 JDK 镜像、 Tomcat 镜像等。
2.4.1.1: 自定义 Centos 基础镜像
docker pull centos
mkdir /opt/dockerfile/{web/{nginx,tomcat,jdk,apache},system/{centos,ubuntu,redhat}} -pv
cd /opt/dockerfile/system/centos/
cat Dockerfile
#Centos Base Image
FROM centos:latest
MAINTAINER zhangshijie [email protected]
RUN rpm -ivh http://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm
RUN yum install -y vim wget tree lrzsz gcc gcc-c++ automake pcre pcre-devel zlib
zlib-devel openssl openssl-devel iproute net-tools iotop
RUN groupadd www -g 2020 && useradd www -u 2020 -g www #添加系统账户
cat build-command.sh #通过脚本构建镜像
#!/bin/bash
docker build -t centos-base:v1 .
bash build-command.sh #通过脚本还行镜像构建
2.4.1.2: 执行构建 JDK 镜像
cd /opt/dockerfile/web/jdk/
cat Dockerfile
#JDK Base Image
FROM centos-base:v1
MAINTAINER zhangshijie "[email protected]"
ADD jdk-8u212-linux-x64.tar.gz /usr/local/src/
RUN ln -sv /usr/local/src/jdk1.8.0_212 /usr/local/jdk
ADD profile /etc/profile
ENV JAVA_HOME /usr/local/jdk
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/:$JRE_HOME/lib/
ENV PATH $PATH:$JAVA_HOME/bin
RUN rm -rf /etc/localtime && ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
2.4.1.3: 上传 JDK 压缩包和 profile 文件
将 JDK 压缩包上传到 Dockerfile 当前目录,然后执行构建
# pwd
/opt/dockerfile/web/jdk
# tree
.
├── build-command.sh
├── Dockerfile
├── jdk-8u212-linux-x64.tar.gz
└── profile
0 directories, 4 files
2.4.1.4: 执行构建自定义 JDK 基础镜像
构建并验证自定义 JDK 基础镜像
2.4.1.4.1: 通过脚本构建
cat build-command.sh
#!/bin/bash
docker build -t jdk-base:v8.212 .
#执行构建
bash build-command.sh
2.4.1.2: 验证镜像 JDK 环境
[root@docker-server1 jdk]# docker run -it jack/ceontos-jdk bash
[root@3373ee6a824e /]# java -version
java version "1.8.0_212"
Java(TM) SE Runtime Environment (build 1.8.0_212-b10)
Java HotSpot(TM) 64-Bit Server VM (build 25.212-b10, mixed mode)
小笔记:构建JDK镜像
mkdir /opt/dockerfile/{web/{nginx,tomcat,jdk,apache},system/{centos,ubuntu,redhat}} -pv
cd /opt/dockerfile/system/centos
vim Dockerfile
FROM centos:7.7.1908
LABEL LiangJC [email protected]
RUN yum install -y epel-release && yum install -y vim wget tree lrzsz gcc gcc-c++ automake pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop
RUN groupadd www -g 2020 && useradd www -u 2020 -g www && groupadd nginx -g 2021 && useradd nginx -u 2021 -g nginx
#构建
docker build -t centos-base:7.7.1908 .
#脚本构建
vim build-command.sh
#!/bin/bash
docker build -t centos-base:7.7.1908 .
#jdk
mkdir -pv /opt/dockerfile/web/{apache,jdk,nginx,tomcat}
cd /opt/dockerfile/web/jdk
mkdir jdk-8u212
cd jdk-8u212
vim Dockerfile
FROM centos-base:7.7.1908
MAINTAINER LiangJC [email protected]
ADD jdk-8u212-linux-x64.tar.gz /usr/local/src/
RUN ln -sv /usr/local/src/jdk1.8.0_212 /usr/local/jdk
ADD profile /etc/profile
ENV JAVA_HOME /usr/local/jdk
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/:$JRE_HOME/lib/
ENV PATH $PATH:$JAVA_HOME/bin
RUN rm -rf /etc/localtime && ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
vim /etc/profile
...
export JAVA_HOME=/usr/local/jdk
export JRE_HOME=$JAVA_HOME/jre
export CLASSPATH=$JAVA_HOME/lib/:$JRE_HOME/lib/
export PATH=$PATH:$JAVA_HOME/bin
docker build -t centos-jdk:8u212 .
docker run -it --rm centos-jdk:8u212 bash
2.4.2: 从 JDK 镜像构建 tomcat 8 Base 镜像
基于自定义的 JDK 基础镜像,构建出通用的自定义 Tomcat 基础镜像,此镜像后期会被多个业务的多个服务共同引用(相同的 JDK 版本和 Tomcat 版本)。
2.4.2.1: 编辑 Dockerfile
pwd
/opt/dockerfile/web/tomcat/tomcat-base
cat Dockerfile
#Tomcat Base Image
FROM jdk-base:v8.212
#env
ENV TZ "Asia/Shanghai"
ENV LANG en_US.UTF-8
ENV TERM xterm
ENV TOMCAT_MAJOR_VERSION 8
ENV TOMCAT_MINOR_VERSION 8.5.45
ENV CATALINA_HOME /apps/tomcat
ENV APP_DIR ${CATALINA_HOME}/webapps
#tomcat
RUN mkdir /apps
ADD apache-tomcat-8.5.45.tar.gz /apps
RUN ln -sv /apps/apache-tomcat-8.5.45 /apps/tomcat
2.4.2.2: 上传 tomcat 压缩包
# tree
.
├── apache-tomcat-8.5.45.tar.gz
├── build-command.sh
└── Dockerfile
0 directories, 3 files
2.4.2.3:通过脚本构建 tomcat 基础镜像
[root@docker-server1 tomcat8-base]# cat build-command.sh
#!/bin/bash
docker build -t tomcat-base:v8.5.45
#执行构建
bash build-command.sh
2.4.3: 构建业务镜像 1
创建 tomcat app1 和 tomcat app2 两个目录, 表示基于 tomcat 自定义基础镜像构建出不同业务的 tomcat app 镜像。
2.4.3.1: 准备 Dockerfile
# pwd
/opt/dockerfile/web/tomcat/tomcat-app1
# cat Dockerfile
#Tomcat Web Image
FROM tomcat-base:v8.5.45
ADD run_tomcat.sh /apps/tomcat/bin/run_tomcat.sh
ADD myapp/* /apps/tomcat/webapps/myapp/
RUN chown www.www /apps/ -R
EXPOSE 8080 8009
CMD ["/apps/tomcat/bin/run_tomcat.sh"]
2.4.3.2: 准备自定义 myapp 页面
# mkdir myapp
# echo "Tomcat Web Page" > myapp/index.html
# cat myapp/index.html
Tomcat Web Page
2.4.3.3: 准备容器启动执行脚本
# cat run_tomcat.sh
#!/bin/bash
echo "1.1.1.1 abc.test.com" >> /etc/hosts
echo "nameserver 223.5.5.5" > /etc/resolv.conf
su - www -c "/apps/tomcat/bin/catalina.sh start"
su - www -c "tail -f /etc/hosts
2.4.3.4:准备构建脚本
[root@docker-server1 tomcat-app1]# cat build-command.sh
#!/bin/bash
docker build -t tomcat-web:app1 .
2.4.3.5: 执行构建
# pwd
/opt/dockerfile/web/tomcat/tomcat-app1
# chmod a+x *.sh
# tree
.
├── build-command.sh
├── Dockerfile
├── myapp
│ └── index.html
└── run_tomcat.sh
1 directory, 4 file
# bash build-command.sh
2.4.3.6:从镜像启动容器测试
docker run -it -d -p 8080:8080 tomcat-web:app1
ad2eef20efe9299deb3289137001690c19f14978a6cc34f8f383df5951ac98a0
小笔记:基于JDK镜像创建Tomcat镜像
#创建tomcat镜像
cd ../tomcat
mkdir tomcat-8.5.51-base
cd tomcat-8.5.51-base
vim Dockerfile
FROM centos-jdk:8u212
LABEL LiangJC [email protected]
ADD apache-tomcat-8.5.51.tar.gz /apps
RUN ln -sv /apps/apache-tomcat-8.5.51 /apps/tomcat
docker build -t centos-tomcat:8.5.51 .
docker run -it --rm centos-tomcat:8.5.51 bash
#创建app1
cd ..
mkdir tomcat-app1
cd tomcat-app1
vim Dockerfile
FROM centos-tomcat:8.5.51
LABEL LiangJC [email protected]
ADD server.xml /apps/tomcat/conf
ADD linux39.tar.gz /data/tomcat/webapps
ADD run_tomcat.sh /apps/tomcat/bin
RUN chown -R www.www /apps
EXPOSE 8080 8005 8009
CMD ["/apps/tomcat/bin/run_tomcat.sh"]
vim server.xml
vim run_tomcat.sh
#!/bin/bash
echo "192.168.37.7 abc.test.com" >> /etc/hosts
echo "nameserver 223.5.5.5" > /etc/resolv.conf
su - www -c "/apps/tomcat/bin/catalina.sh start"
tail -f /etc/hosts
chmod +x run_tomcat.sh
docker build -t tomcat-linux39:app1 .
2.4.4.: 构建业务镜像 2
第二个 tomcat 服务镜像
2.4.4.1:准备 Dockerfile
# pwd
/opt/dockerfile/web/tomcat/tomcat-app2
# cat Dockerfile
#Tomcat Web Image
FROM tomcat-base:v8.5.45
ADD run_tomcat.sh /apps/tomcat/bin/run_tomcat.sh
ADD myapp/* /apps/tomcat/webapps/myapp/
RUN chown www.www /apps/ -R
EXPOSE 8080 8009
CMD ["/apps/tomcat/bin/run_tomcat.sh"]
2.4.4.2: 准备自定义页面
mkdir myapp
echo "Tomcat Web Page2" > myapp/index.html
cat myapp/index.html
Tomcat Web Page2
2.4.4.3:准备容器启动脚本
# cat run_tomcat.sh
#!/bin/bash
echo "1.1.1.1 abc.test.com" >> /etc/hosts
echo "nameserver 223.5.5.5" > /etc/resolv.conf
su - www -c "/apps/tomcat/bin/catalina.sh start"
su - www -c "tail -f /etc/hosts"
2.4.4.4: 准备构建脚本
# cat build-command.sh
#!/bin/bash
docker build -t tomcat-web:app2 .
2.4.4.5: 执行构建
# pwd
/opt/dockerfile/web/tomcat/tomcat-app2
# bash build-command.sh
2.4.4.6: 从镜像启动容器
# docker run -it -d -p 8081:8080 tomcat-web:app2
fa01784532f09c04da3ab0f81efdee7aefebc15c8f6dbfbf00a9bbc566e6f597
2.5:构建 haproxy 镜像
构建出 haproxy 镜像,将 haproxy 通过容器的方式运行。
2.5.1:准备 Dockerfile
# pwd
/opt/dockerfile/web/haproxy
# cat Dockerfile
#Haproxy Base Image
FROM centos-base:v1
MAINTAINER zhangshijie "[email protected]"
RUN yum install -y yum install gcc gcc-c++ glibc glibc-devel pcre pcre-devel openssl
openssl-devel systemd-devel net-tools vim iotop bc zip unzip zlib-devel lrzsz tree s
creen lsof tcpdump wget ntpdate ADD haproxy-2.0.5.tar.gz /usr/local/src/
RUN cd /usr/local/src/haproxy-2.0.5 && make ARCH=x86_64 TARGET=linuxglibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1
USE_CPU_AFFINITY=1 PREFIX=/usr/local/hap
roxy && make install PREFIX=/usr/local/haproxy && cp haproxy /usr/sbin/ &&
mkdir /usr/local/haproxy/runADD haproxy.cfg /etc/haproxy/
ADD run_haproxy.sh /usr/bin
EXPOSE 80 9999
CMD ["/usr/bin/run_haproxy.sh"]
2.5.2: 准备 haproxy 源码和配置文件
# pwd
/opt/dockerfile/web/haproxy
# ll
total 2496
drwxr-xr-x 2 root root 117 Sep 12 15:31 ./
drwxr-xr-x 7 root root 73 Sep 12 15:23 ../
-rwxr-xr-x 1 root root 44 Sep 12 15:30 build-command.sh*
-rw-r--r-- 1 root root 717 Sep 12 15:31 Dockerfile
-rw-r--r-- 1 root root 2539226 Sep 12 15:22 haproxy-2.0.5.tar.gz
-rw-r--r-- 1 root root 673 Sep 12 15:30 haproxy.cfg
-rwxr-xr-x 1 root root 67 Aug 3 2018 run_haproxy.sh*
2.5.3: 准备 haproxy 配置文件
# cat haproxy.cfg
global
chroot /usr/local/haproxy
#stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
uid 99
gid 99
daemon
nbproc 1
pidfile /usr/local/haproxy/run/haproxy.pid
log 127.0.0.1 local3 info
defaults
option http-keep-alive
option forwardfor
mode http
timeout connect 300000ms
timeout client 300000ms
timeout server 300000ms
listen stats
mode http
bind 0.0.0.0:9999
stats enable
log global
stats uri /haproxy-status
stats auth haadmin:123456
listen web_port
bind 0.0.0.0:80
mode http
log global
balance roundrobin
server web1 192.168.37.17:8080 check inter 3000 fall 2 rise 5
server web2 192.168.37.27:8080 check inter 3000 fall 2 rise 5
2.5.4: 准备镜像构建脚本
# cat build-command.sh
#!/bin/bash
docker build -t haproxy:2.0.5 .
2.5.5: 执行构建 haproxy 镜像
bash build-command.sh
2.5.6: 从镜像启动容器
# docker run -it -d -p 80:80 -p 9999:9999 haproxy:2.0.5
d20e821a82e4a4a8b2d4b4c7f79f4750e5b3878bf10b43d30bd3ad2196687afa
小笔记:制作haproxy镜像
cd /opt/dockerfile/web/haproxy
vim Dockerfile
FROM centos:7.7.1908
LABEL LiangJC [email protected]
RUN yum install -y yum install gcc gcc-c++ glibc glibc-devel pcre pcre-devel openssl openssl-devel systemd-devel net-tools vim iotop bc zip unzip zlib-devel lrzsz tree screen lsof tcpdump wget ntpdate
ADD haproxy-2.0.13.tar.gz /usr/local/src/
RUN cd /usr/local/src/haproxy-2.0.13 && make ARCH=x86_64 TARGET=linuxglibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_CPU_AFFINITY=1 PREFIX=/usr/local/haproxy && make install PREFIX=/usr/local/haproxy && cp haproxy /usr/sbin/ && mkdir /usr/local/haproxy/run
ADD haproxy.cfg /etc/haproxy/
ADD run_haproxy.sh /usr/bin
EXPOSE 80 9999
CMD ["/usr/bin/run_haproxy.sh"]
vim run_haproxy.sh
#!/bin/bash
haproxy -f /etc/haproxy/haproxy.cfg
tail -f /etc/hosts
chmod +x run_haproxy.sh
vim haproxy.cfg
global
chroot /usr/local/haproxy
#stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
uid 99
gid 99
daemon
nbproc 1
pidfile /usr/local/haproxy/run/haproxy.pid
log 127.0.0.1 local3 info
defaults
option http-keep-alive
option forwardfor
mode http
timeout connect 300000ms
timeout client 300000ms
timeout server 300000ms
listen stats
mode http
bind 0.0.0.0:9999
stats enable
log global
stats uri /haproxy-status
stats auth haadmin:123456
listen web_port
bind 0.0.0.0:80
mode http
log global
balance roundrobin
server web1 192.168.7.101:8080 check inter 3000 fall 2 rise 5
server web2 192.168.7.102:8080 check inter 3000 fall 2 rise 5
docker build -t haproxy:2.0.13-centos .
#web1:tomcat-linux39:app1
#web2:tomcat-linux39:app2
#导出到tomcat-app2
docker save tomcat-linux39:app2 > /opt/app2.tar.gz
scp /opt/app2.tar.gz [email protected]:/opt
docker load -i /opt/app2.tar.gz
#haproxy+nginx+tomcat
#harpoxy:80 nginx:81 tomcat:8080
#两台机器
#serverA
docker start id(tomcat-app1)
cd /opt/dockerfile/web/nginx-alpine
vim nginx.conf
http {
upstream tomcat {
server 192.168.37.17:8080;
server 192.168.37.27:8080;
}
...
server {
...
location /linux39 {
proxy_pass http://tomcat/;
}
...
}
}
docker build -t nginx:1.16.1-alpine
docker run -d -it -p 81:80 nginx:1.16.1-alpine .
cd /opt/dockerfile/web/haproxy
vim haproxy
server web1 192.168.7.101:81 check inter 3000 fall 2 rise 5
server web2 192.168.7.102:81 check inter 3000 fall 2 rise 5
docker build -t haproxy:2.0.13-centos .
docker save nginx-ID > /opt/nginx.tar.gz
docker save haproxy-ID > /opt/haproxy.tar.gz
scp /opt/nginx.tar.gz [email protected]:/opt
scp /opt/haproxy.tar.gz [email protected]:/opt
#serverB
docker start id(tomcat-app2)
docker load -i /opt/nginx.tar.gz
docker run -d -it -p 81:80 nginx:1.16.1-alpine
2.6:基于官方 alpine 基础镜像制作自定义镜像
FROM alpine
maintainer zhangshijie "[email protected]"
COPY repositories /etc/apk/repositories
RUN apk update && apk add iotop gcc libgcc libc-dev libcurl libc-utils pcre-dev zlib-dev libnfs make pcre pcre2 zip unzip net-tools pstree wget libevent libeventdev iproute2
ADD nginx-1.16.1.tar.gz /opt/
RUN cd /opt/nginx-1.16.1 && ./configure --prefix=/apps/nginx && make && make install && ln -sv /apps/nginx/sbin/nginx /usr/bin/
RUN addgroup -g 2019 -S nginx && adduser -s /sbin/nologin -S -D -u 2019 -G nginx nginx
COPY nginx.conf /apps/nginx/conf/nginx.conf
ADD static.tar.gz /data/nginx/html
RUN chown nginx.nginx /data/nginx/ /apps/nginx/ -R
EXPOSE 80 443
CMD ["nginx"]
小笔记:基于alpine制作nginx镜像
#基本使用
apk #软件管理命令,类似yum,apt
apk add vim #安装软件
#Dockerfile
cd /opt/dockerfile/web/nginx-alpine
vim repositories
http://mirrors.aliyun.com/alpine/v3.11/main
http://mirrors.aliyun.com/alpine/v3.11/community
vim Dockerfile
FROM alpine
LABEL LiangJC "[email protected]"
ADD repositories /etc/apk/repositories
RUN apk update && apk add iotop gcc libgcc libc-dev libcurl libc-utils pcre-dev zlib-dev libnfs make pcre pcre2 zip unzip net-tools pstree wget libevent libevent-dev iproute2
ADD nginx-1.16.1.tar.gz /usr/local/src
RUN cd /usr/local/src/nginx-1.16.1 && ./configure --prefix=/apps/nginx && make && make install
RUN ln -sv /apps/nginx/sbin/nginx /usr/sbin
ADD nginx.conf /apps/nginx/conf
ADD static.tar.gz /data/nginx/html
RUN addgroup -g 2020 -S nginx && adduser -s /sbin/nologin -S -u 2020 -G nginx nginx
RUN chown nginx.nginx /data/nginx/ /apps/nginx/ -R
EXPOSE 80 443
CMD ["nginx"]
#构建
docker build -t nginx-1.16.1-alpine .
2.7:基于官方 Ubuntu 基础镜像制作自定义镜像
# cat Dockerfile
FROM ubuntu:18.04
maintainer zhangshijie "[email protected]"
COPY sources.list /etc/apt/sources.list
RUN apt update && apt install -y iproute2 ntpdate tcpdump telnet traceroute nfs-kernel-server nfs-common lrzsz tree openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev ntpdate tcpdump telnet traceroute gcc openssh-server lrzsz tree openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev ntpdate tcpdump telnet traceroute iotop unzip zip make && touch /tmp/linux.txt
ADD nginx-1.16.1.tar.gz /usr/local/src
RUN cd /usr/local/src/nginx-1.16.1 && ./configure --prefix=/apps/nginx && make && make install && ln -sv /apps/nginx/sbin/nginx /usr/bin && rm -rf /usr/local/src/nginx-1.16.1 && rm -rf /usr/local/src/nginx-1.16.1.tar.gz
ADD nginx.conf /apps/nginx/conf/nginx.conf
ADD static.tar.gz /data/nginx/html
RUN groupadd -g 2019 nginx && useradd -g nginx -s /usr/sbin/nologin -u 2019 nginx && chown -R nginx.nginx /apps/nginx /data/nginx
EXPOSE 80 443
CMD ["nginx"]
小笔记:基于ubuntu制作nginx镜像
cd /opt/dockerfile/web/nginx-ubuntu
cp ../nginx-alpine/nginx-1.16.1.tar.gz .
cp ../nginx-alpine/nginx.conf .
cp ../nginx-alpine/static.zip .
#Dockerfile
vim Dockerfile
FROM ubuntu:18.04
LABEL LiangJC "[email protected]"
ADD sources.list /etc/apt/sources.list
RUN apt update && apt install -y iproute2 ntpdate tcpdump telnet traceroute nfs-kernel-server nfs-common lrzsz tree openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev ntpdate tcpdump telnet traceroute gcc openssh-server lrzsz tree openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev ntpdate tcpdump telnet traceroute iotop unzip zip make
ADD nginx-1.16.1.tar.gz /usr/local/src
RUN cd /usr/local/src/nginx-1.16.1 && ./configure --prefix=/apps/nginx && make && make install
RUN ln -sv /apps/nginx/sbin/nginx /usr/sbin
ADD nginx.conf /apps/nginx/conf
ADD static.tar.gz /data/nginx/html
RUN groupadd -g 2019 nginx && useradd -g nginx -s /usr/sbin/nologin -u 2019 nginx && chown -R nginx.nginx /apps/nginx /data/nginx
EXPOSE 80 443
CMD ["nginx"]
#构建
docker build -t nginx-1.16.1-ubuntu .
2.8: 本地镜像上传至官方 docker 仓库
将自制的镜像上传至 docker 仓库; https://hub.docker.com/, 实现镜像夸主机备份。
2.8.1: 准备账户:
登录到 docker hub 创建官网创建账户, 登录后点击 settings 完善账户信息
2.8.2: 在虚拟机使用自己的账号登录
docker login docker.io
Username:
Password
2.8.3: 查看认证信息
登录成功之后会在当前目录生成一个隐藏文件用于保存登录认证信息
# cat /root/.docker/config.json
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "emhhbmdzaGlqaWU6emhhbmdAMTIz"
}
},
"HttpHeaders": {
"User-Agent": "Docker-Client/18.09.9 (linux)"
}
}
root@docker-server1:/opt/dockerfile/system/centos#
2.8.5: 给镜像做 tag 并开始上传
[root@linux-docker ~]# docker images #查看镜像 ID
#为镜像做标记并上传至仓库
docker tag alpine:latest docker.io/zhangshijie/alpine:latest
docker push docker.io/zhangshijie/alpine:latest
#小笔记:
docker tag alpine:latest docker.io/zhangshijie/linux39/alpine:latest
docker push docker.io/zhangshijie/linux39/alpine:20200219
2.8.6: 更换到其他 docker 服务器下载镜像
docker login https://hub.docker.com
docker pull zhangjie/alpine-test
2.9: 本地镜像上传到阿里云
将本地镜像上传至阿里云, 实现镜像备份与统一分发的功能。
https://cr.console.aliyun.com
注册账户、 创建 namespace、 创建仓库、修改镜像 tag 及上传镜像
# docker login [email protected] registry.cn-hangzhou.aliyuncs.com
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
将镜像推送到 Registry
# docker login [email protected] registry.cn-hangzhou.aliyuncs.com
# docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/magedu/nginx:[镜像版本号]
# docker push registry.cn-hangzhou.aliyuncs.com/ magedu /nginx:[镜像版本号]
三: Docker 数据管理
如果正在运行中的容器修如果生成了新的数据或者修改了现有的一个已经存在的文件内容, 那么新产生的数据将会被复制到读写层进行持久化保存, 这个读写层也就是容器的工作目录,此即“写时复制(COW) copy on write”机制。
如下图是将对根的数据写入到了容器的可写层, 但是把/data 中的数据写入到了一个另外的 volume 中用于数据持久化。
3.1: 数据类型
Docker 的镜像是分层设计的,镜像层是只读的,通过镜像启动的容器添加了一层可读写的文件系统,用户写入的数据都保存在这一层当中。
如果要将写入到容器的数据永久保存, 则需要将容器中的数据保存到宿主机的指定目录,目前 Docker 的数据类型分为两种:
一是数据卷(data volume), 数据卷类似于挂载的一块磁盘,数据容器是将数据保存在一个容器上.
二是数据卷容器(Data volume container), 数据卷容器是将宿主机的目录挂载至一个专门的数据卷容器,然后让其他容器通过数据卷容器读写宿主机的数据
root@s1:~# docker inspect f55c55544e05 #查看指定 PID 的容器信息
LowerDir: image 镜像层(镜像本身,只读)
UpperDir:容器的上层(读写)
MergedDir:容器的文件系统,使用 Union FS(联合文件系统)将 lowerdir 和 upperdir 合并给容器使用。
WorkDir:容器在 宿主机的工作目录
在容器生成数据
# docker exec -it fa01784532f0 bash
[root@fa01784532f0 /]# dd if=/dev/zero of=file bs=1M count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 0.257476 s, 407 MB/s
[root@fa01784532f0 /]# md5sum file
2f282b84e7e608d5852449ed940bfc51 file
# cp anaconda-post.log /opt/
3.1.1: 什么是数据卷(data volume)
数据卷实际上就是宿主机上的目录或者是文件,可以被直接 mount 到容器当中使用。
实际生产环境中,需要针对不同类型的服务、 不同类型的数据存储要求做相应的规划, 最终保证服务的可扩展性、 稳定性以及数据的安全性。
如下图:
左侧是无状态的 http 请求服务, 右侧为有状态。
下层为不需要存储的服务,上层为需要存储的部分服务。
3.1.1.1: 创建 APP 目录并生成 web 页面
此 app 以数据卷的方式,提供给容器使用, 比如容器可以直接宿主机本地的 web app,而需要将代码提前添加到容器中,此方式适用于小型 web 站点。
# mkdir /data/testapp –p
# echo "testapp page" > /data/testapp/index.html
# cat /data/testapp/index.html
testapp page
3.1.1.2: 启动容器并验证数据:
启动两个容器, web1 容器和 web2 容器, 分别测试能否在宿主机访问到宿主机的数据。
#注意使用-v 参数, 将宿主机目录映射到容器内部, web2 的 ro 标示在容器内对该目录只读,默认是可读写的
root@docker-server1:~# docker run -d --name web1 -v
/data/testapp/:/apps/tomcat/webapps/testapp -p 8080:8080 tomcat-web:app1
463bf7548b724c74c99d2c583831af680a0b9575a1d62206311898a759bc823b
# docker run -d --name web2 -v /data/testapp/:/apps/tomcat/webapps/testapp:ro -p 8081:8080 tomcatweb:app2
999ed545ca948551d3a51338a0080c1ea45b3f8446e7454b880e8c8cde269ba8
3.1.1.3: 进入到容器内测试写入数据
3.1.1.4: 宿主机验证
验证宿主机的数据是否正常
3.1.1.5: web 界面访问
3.1.1.6: 在宿主机或容器修改数据
[root@docker-server1 ~]# echo "1111" >> testapp/index.html
[root@docker-server1 ~]# cat testapp/index.html
Test App Page
docker
1111
3.1.1.7: web 端访问验证数据
[图片上传失败...(image-be3b21-1594392637196)]
3.1.1.8: 删除容器
创建容器的时候指定参数-v, 可以删除/var/lib/docker/containers/的容器数据目录,但是不会删除数据卷的内容,如下
3.1.1.9: 验证宿主机的数据
# cat /data/testapp/index.html
testapp page
web v2
3.1.1.10:数据卷的特点及使用
1、数据卷是宿主机的目录或者文件,并且可以在多个容器之间共同使用。
2、 在宿主机对数据卷更改数据后会在所有容器里面会立即更新。
3、数据卷的数据可以持久保存,即使删除使用使用该容器卷的容器也不影响。
4、 在容器里面的写入数据不会影响到镜像本身。
小笔记:数据卷使用
mkdir -pv /data/tomcat/webapps/myapp
vim /data/tomcat/webapps/myapp/index.html
linux39 tomcat app1
docker run -it -d -p 8080:8080 -v /data/tomcat/webapps/myapp:/data/tomcat/webapps/myapp tomcat-linux39:app1
docker run -it -d -p 8080:8080 -v /data/tomcat/webapps/myapp:/data/tomcat/webapps/myapp:ro tomcat-linux39:app1 #只读挂载
http://172.31.6.101:1080
3.1.2: 文件挂载
文件挂载用于很少更改文件内容的场景, 比如 nginx 的配置文件、 tomcat 的配置文件等。
3.1.2.1: 创建容器并挂载配置文件
# ll /data/testapp/
total 28
drwxr-xr-x 2 root root 43 Sep 12 17:40 ./
drwxr-xr-x 4 root root 35 Sep 12 17:10 ../
-rwxr-xr-x 1 root root 23611 Aug 5 2018 catalina.sh*
-rw-r--r-- 1 root root 20 Sep 12 17:22 index.html
自定义 JAVA 选项参数
JAVA_OPTS="-server -Xms4g -Xmx4g -Xss512k -Xmn1g -XX:CMSInitiatingOccupancyFraction=65 -XX:+UseFastAccessorMethods -XX:+AggressiveOpts -XX:+UseBiasedLocking -XX:+DisableExplicitGC -XX:MaxTenuringThreshold=10 -XX:NewSize=2048M -XX:MaxNewSize=2048M -XX:NewRatio=2 -XX:PermSize=128m -XX:MaxPermSize=512m -XX:CMSFullGCsBeforeCompaction=5 -XX:+ExplicitGCInvokesConcurrent -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods"
创建容器
# docker run -it -d -p 8080:8080 -v
/data/testapp/catalina.sh:/apps/tomcat/bin/catalina.sh:ro tomcat-web:app2
2e90299a39163d7c3af97888b84f02f2c3481529fcf6a9da8f06fbb92bd05f7c
3.1.2.2: 验证参数生效
docker ps
3.1.2.3: 进入容器测试文件读写
root@docker-server1:~# docker exec -it 2e90299a3916 bash
[root@2e90299a3916 /]# echo "test" >> /apps/tomcat/bin/catalina.sh
bash: /apps/tomcat/bin/catalina.sh: Read-only file system
[root@2e90299a3916 /]#
3.1.2.3: 如何一次挂载多个目录
多个目录可以位于不同的目录下
root@docker-server1:~# mkdir /data/magedu
root@docker-server1:~# echo "magedu" >> /data/magedu/index.html
# docker run -d --name web1 -p 8081:8080 -v
/data/testapp/catalina.sh:/apps/tomcat/bin/catalina.sh:ro -v data/magedu/:/apps/tomcat/webapps/testapp tomcatweb:app1
491b5acd8426d125dc747b6a90990513d655fac4573597bd13afb330ca1c2dd4
再启动一个容器, 验证宿主机目录或文件是否共享:
~# docker run -d --name web2 -p 8082:8080 -v /data/testapp/catalina.sh:/apps/tomcat/bin/catalina.sh:ro -v /data/magedu/:/apps/tomcat/webapps/testapp tomcat-web:app2
b07b9c09c8cadca8a8ef9e4e5c3969f3713a47280e9e5608fb8bd4e11ec45128
3.1.2.4: 验证 web 访问
http://192.168.7.101:8081
http://192.168.7.101:8082
3.1.2.5:数据卷使用场景
1、 日志输出
2、 静态 web 页面
3、 应用配置文件
4、 多容器间目录或文件共享
小笔记:文件挂载
#tomcat启动脚本
vim catalina.sh
#放在最上面
JAVA_OPTS="-server -Xms4g -Xmx4g -Xss512k -Xmn1g -XX:CMSInitiatingOccupancyFraction=65 -XX:+UseFastAccessorMethods -XX:+AggressiveOpts -XX:+UseBiasedLocking -XX:+DisableExplicitGC -XX:MaxTenuringThreshold=10 -XX:NewSize=2048M -XX:MaxNewSize=2048M -XX:NewRatio=2 -XX:PermSize=128m -XX:MaxPermSize=512m -XX:CMSFullGCsBeforeCompaction=5 -XX:+ExplicitGCInvokesConcurrent -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods"
chmod +x catalina.sh
docker run -it -d -p 8080:8080 -v /data/tomcat/webapps/myapp:/data/tomcat/webapps/myapp -v /data/tomcat/conf/server.xml:/apps/tomcat/conf/server.xml:ro -v /data/tomcat/bin/catalina.sh:/data/tomcat/bin/catalina.sh:ro tomcat-linux39:app1
#nginx,tomcat日志输出
docker run -it -d -p 80:80 -v /data/logs/nginx:/apps/nginx/logs nginx:1.16.1-alpine
docker run -it -d -p 8080:8080 -v /data/logs/tomcat:/apps/tomcat/logs tomcat-linux39:app1
3.1.3: 数据卷容器
数据卷容器功能是可以让数据在多个 docker 容器之间共享,即可以让 B 容器访问 A 容器的内容,而容器 C 也可以访问 A 容器的内容, 即先要创建一个后台运行的容器作为 Server, 用于卷提供, 这个卷可以为其他容器提供数据存储服务,其他使用此卷的容器作为 client 端
3.1.3.1:启动一个卷容器 Server
先启动一个容器, 并挂载宿主机的数据目录:
将宿主机的 catalina.sh 启动脚本和 magedu 的 web 页面,分别挂载到卷容器 server端,然后通过 server 端共享给 client 端使用。
# docker rm -fv web1 web2
# docker run -d --name volume-server -v /data/testapp/catalina.sh:/apps/tomcat/bin/catalina.sh:ro -v /data/magedu:/apps/tomcat/webapps/magedu tomcat-web:app2
33bc02c22cae0261731e0aa24ae2c663322b7888ed0ba5958b91f71616df19c4
3.1.3.2:启动两个端容器 Client
# docker run -d --name web1 -p 8801:8080 --volumes-from volume-server tomcatweb:app1
ac657e2cd03e12e57b6b093d563120279556138018e0bbc9655dda59507fed46
# docker run -d --name web2 -p 8802:8080 --volumes-from volume-server tomcatweb:app2
ec50686a98fa7bbb0a3b53ed27f18d166236f132ab187c82bad37eb1ab329fa0
3.1.3.3: 分别进入容器测试读写
读写权限依赖于源数据卷 Server 容器
3.1.3.4: 测试访问 web 页面
http://192.168.7.101:8081/testapp
http://192.168.7.101:8082/testapp
3.1.3.5: 验证宿主机数据
# cat /data/magedu/index.html
magedu
magedu v2
3.1.3.6: 关闭卷容器 Server 测试能否启动新容器
# docker stop volume-server
volume-server
#测试停止完成之后能否创建新的容器,停止 volume server 是可以创建新容器的。
# docker run -d --name web3 -p 8803:8080 --volumes-from volume-server tomcatweb:app2
1ab11ec011668bb04225702961bb1a0b520a47a7de49134cd7b301cffeaaf5dd
3.1.3.7: 测试删除源卷容器 Server 创建容器
将 volume server 删除,然后在测试能否创建基于 volume server 的新容器。
# docker rm -fv volume-server
volume-server
# docker run -d --name web4 -p 8804:8080 --volumes-from volume-server tomcatweb:app2
docker: Error response from daemon: No such container: volume-server.
See 'docker run --help'.
3.1.3.8: 测试之前的容器是否正常
已经运行的容器不受任何影响
http://192.168.7.101:8081/testapp
http://192.168.7.101:8082/testapp
3.1.3.9: 重新创建容器卷 Server
# docker run -d --name volume-server -v /data/testapp/catalina.sh:/apps/tomcat/bin/catalina.sh:ro -v /data/magedu:/apps/tomcat/webapps/magedu tomcat-web:app2
4cacb3a92de9ec7db948c41db04853793fdab50a2d70d37d31b4d55a7463ce2b
#创建出 volume server 之后, 就可以创建基于 volume server 的新容器。
# docker run -d --name web4 -p 8804:8080 --volumes-from volume-server tomcatweb:app2
244908c41af7fa709b96bbcb95388da1f138c4b7bbbf822ba3ed79929a1cd8b9
在当前环境下, 即使把提供卷的容器 Server 删除, 已经运行的容器 Client 依然
可以使用挂载的卷, 因为容器是通过挂载访问数据的, 但是无法创建新的卷容器
客户端, 但是再把卷容器 Server 创建后即可正常创建卷容器 Client,此方式可以
用于线上共享数据目录等环境, 因为即使数据卷容器被删除了,其他已经运行的
容器依然可以挂载使用
数据卷容器可以作为共享的方式为其他容器提供文件共享,类似于 NFS 共享,
可以在生产中启动一个实例挂载本地的目录,然后其他的容器分别挂载此容器的
目录,即可保证各容器之间的数据一致性。
小笔记:数据卷容器共享
#启动一个卷容器 Server
docker run -d -it --name volume-server -v /data/tomcat/webapps/mysapp:/data/tomcat/webapps/mysapp:ro -v /data/tomcat/conf/server.xml:/data/tomcat/conf/server.xml:ro -v /data/tomcat/bin/catalina.sh:/apps/tomcat/bin/catalina.sh:ro tomcat-linux39:app1
#启动两个端容器 Client
docker run -it -d -p 8080:8080 --name app-client1 --volumes-from volume-server tomcat-linux39:app1
docker run -it -d -p 8081:8080 --name app-client2 --volumes-from volume-server tomcat-linux39:app1