有助于持续集成和部署的 容器虚拟化技术,运行环境和配置的标准化解决方案。
解决环境配置的难题(软件带环境安装)。
常用的两种用于解决带环境安装技术,虚拟机技术和容器虚拟化技术
虚拟机(virtual machine)就是带环境安装的一种解决方案。它可以在一种操作系统里面运行另一种操作系统,比如在 Windows 系统里面运行 Linux 系统。应用程序对此毫无感知,因为虚拟机看上去跟真实系统一模一样,而对于底层系统来说,虚拟机就是一个普通文件,不需要了就删掉,对其他部分毫无影响。
资源占用多
虚拟机会独占一部分内存和硬盘空间。它运行的时候,其他程序就不能使用这些资源了。哪怕虚拟机里面的应用程序,真正使用的内存只有 1MB,虚拟机依然需要几百 MB 的内存才能运行。
冗余步骤多
虚拟机是完整的操作系统,一些系统级别的操作步骤,往往无法跳过,比如用户登录。
启动慢
启动操作系统需要多久,启动虚拟机就需要多久。可能要等几分钟,应用程序才能真正运行。
容器虚拟化不是模拟一个完整的操作系统,而是对进程进行隔离。或者说,在正常进程的外面套了一个保护层。对于容器里面的进程来说,它接触到的各种资源都是虚拟的,从而实现与底层系统的隔离。由于容器是进程级别的,相比虚拟机有很多优势。
启动快
容器里面的应用,直接就是底层系统的一个进程,而不是虚拟机内部的进程。所以,启动容器相当于启动本机的一个进程,而不是启动一个操作系统,速度就快很多。
资源占用少
容器只占用需要的资源,不占用那些没有用到的资源;虚拟机由于是完整的操作系统,不可避免要占用所
有资源。另外,多个容器可以共享资源,虚拟机都是独享资源。
体积小
容器只要包含用到的组件即可,而虚拟机是整个操作系统的打包,所以容器文件比虚拟机文件要小很多。
虚拟机和容器虚拟化比较
虚拟化的封装是系统级的封装,docker 或者其他容器是进程级的封装。
特性 | 容器 | 虚拟机 |
---|---|---|
启动速度 | 秒级 | 分钟级 |
性能 | 接近原生 | 较弱 |
内存代价 | 很小 | 较多 |
硬盘使用 | 一般为MB | 一般为GB |
运行密度 | 单机支持上千个容器 | 一般几十个 |
隔离性 | 安全隔离 | 安全隔离 |
迁移性 | 优秀 | 一般 |
docker run 具有自动抓取 Image 文件的功能。如果发现本地没有指定的 Image 文件,就会从仓库自动抓取。
# 1.启动docker
systemctl start docker 或 service docker start
# 2.设置开机启动docker服务:
systemctl enable docker
# 3.关闭docker
systemctl stop docker 或 service docker stop
# 4.重启docker
systemctl restart docker 或 service docker restart
# 5.查看docker 版本号和详细信息
docker version
docker info
# 6.docker 帮助命令
docker --help # 忘记了docker有哪些命令,便可使用此进行查看与回顾
docker pull --help # 拉取命令 不知道可以带哪些参数,可以这样使用
# 1.查看服务器中docker镜像列表
docker images
# 2.搜索镜像
docker search 镜像名
docker search --filter=STARS=9000 mysql # 搜索 STARS >9000的 mysql 镜像
# 3.拉取镜像
docker pull 镜像名 # 不加tag(版本号) 即拉取docker仓库中该镜像的最新版本latest
docker pull 镜像名:tag # 加:tag 则是拉取指定版本
# 4.删除镜像 ------当前镜像没有被任何容器使用才可以删除
docker rmi -f 镜像名/镜像ID # 删除一个
docker rmi -f 镜像名/镜像ID 镜像名/镜像ID 镜像名/镜像ID # 删除多个,镜像ID或镜像名用空格隔开即可
docker rmi -f $(docker images -aq) # 删除全部镜像 -a 意思为显示全部, -q 意思为只显示ID
# 5.强制删除镜像
docker image rm -f 镜像名称/镜像ID
# 6.保存镜像
docker save 镜像名/镜像ID -o 镜像保存的位置与名字 # docker save tomcat -o haha/myTomcat.tar
# 7.加载镜像
docker load -i 镜像保存文件位置
# 8.给镜像打标签
docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
docker tag 源镜像名:TAG 想要生成新的镜像名:新的TAG
# 8.1 如果省略TAG 则会为镜像默认打上latest TAG
docker tag aaa bbb # 等于 docker tag aaa:latest bbb:test
# 9.上传镜像到docker hub仓库
docker push/: # docker push pikaiqu/myTomcat:0001
# 10.查看指定镜像的创建历史。
docker history pikaqiu/ubuntu:v3
# 11.从容器创建一个新的镜像
docker commit -a "pikaqiu.com" -m "my apache" a404c6c174a2 mymysql:v1 # 将容器a404c6c174a2 保存为新的镜像,并添加提交人信息和说明信息。
# 1.查看正在运行容器列表
docker ps
# 2.查看所有容器 -----包含正在运行 和已停止的
docker ps -a
# 3. 创建容器但不运行
docker create -p 3000:80 --name exampleApp pikaqiu/exampleapp
# 4.运行一个容器
docker run -it -d --name 要取的别名 镜像名:Tag /bin/bash # -it 表示 与容器进行交互式启动 -d 表示可后台运行容器 (守护式运行) --name 给要运行的容器 起的名字 /bin/bash 交互路径
# 5.删除容器
docker rm -f 容器名/容器ID # 删除一个容器
docker rm -f 容器名/容器ID 容器名/容器ID # 删除多个容器,空格隔开要删除的容器名或容器ID
docker rm -f $(docker ps -aq) # 删除全部容器
# 6.容器端口与服务器端口映射
docker run -itd --name redis001 -p 8888:6379 redis:5.0.5 /bin/bash
# 7.进入容器
# 7.1 方式一
docker exec -it 容器名/容器ID /bin/bash # docker exec -it redis001 /bin/bash
# 7.2 方式二
docker attach 容器名/容器ID
# 8.从容器内 退出到自己服务器中
exit # 直接退出 未添加 -d(持久化运行容器) 时 执行此参数 容器会被关闭
Ctrl + p + q # 优雅退出 --- 无论是否添加-d 参数 执行此命令容器都不会被关闭
# 9.停止容器
docker stop 容器ID/容器名
# 10.重启容器
docker restart 容器ID/容器名
# 11.启动容器
docker start 容器ID/容器名
# 12.强制停止容器
docker kill 容器ID/容器名
# 13.容器文件拷贝 --- 无论容器是否开启 都可以进行拷贝,docker cp 容器ID/名称:文件路径 要拷贝到外部的路径 或 要拷贝到外部的路径 容器ID/名称:文件路径
# 13.1 从容器内拷出
docker cp 容器ID/名称: 容器内路径 容器外路径
# 13.2 从外部 拷贝文件到容器内
docker cp 容器外路径 容器ID/名称: 容器内路径
# 14.查看容器日志
docker logs -f --tail=要查看末尾多少行 默认all 容器ID
# 15.目录挂载
# -v 宿主机文件存储位置:容器内文件位置
# 运行一个docker redis 容器 进行 端口映射 两个数据卷挂载 设置开机自启动
docker run -d -p 6379:6379 --name redis001 --restart=always -v /var/lib/redis/data/:/data -v /var/lib/redis/conf/:/usr/local/etc/redis/redis.conf redis:5.0.5 --requirepass "password"
# 16.更换容器名
docker rename 容器ID/容器名 新容器名
# 1.查看镜像、容器、数据卷所占的空间大小
docker system df
# 2.删除异常停止的容器
docker rm `docker ps -a | grep Exited | awk '{print $1}'`
# 3.删除名称或标签为none的镜像
docker rmi -f `docker images | grep '' | awk '{print $3}'`
# 4.查找大文件
find / -type f -size +100M -print0 | xargs -0 du -h | sort -nr
# 5.查找指定docker使用目录下大于指定大小文件
find / -type f -size +100M -print0 | xargs -0 du -h | sort -nr |grep '/var/lib/docker/overlay2/*'
# 1.创建一个新的 Docker 网络
# -d 参数指定 Docker 网络类型,有 bridge overlay。其中 overlay 网络类型用于 Swarm mode
docker network create -d bridge my-net
# 2.连接容器
# 2.1 运行一个容器并连接到新建的 my-net 网络
docker run -it --rm --name busybox1 --network my-net busybox sh
# 2.2 打开新的终端,再运行一个容器并加入到 my-net 网络
docker run -it --rm --name busybox2 --network my-net busybox sh
# 3.通过 ping 来证明 busybox1 容器和 busybox2 容器建立了互联关系
# 3.1 在busybox1 中ping busybox2
ping busybox2
# 3.2 在busybox2中 ping busybox1
ping busybox1
Dockerfile仅仅是用来制作镜像的源码文件,是构建容器过程中的指令,docker能够读取dockerfile的指定进行自动构建容器,基于dockerfile制作镜像,每一个指令都会创建一个镜像层,即镜像都是多层叠加而成(如图所示),因此,层越多,效率越低,创建镜像,层越少越好。因此能在一个指令完成的动作尽量通过一个指令定义。
Docker镜像都是只读的,当容器启动时,一个新的可写层镜像加载到镜像顶部,这一层就是我们通常说的容器层,容器之下的都叫镜像层。 分层 :现在构建一个镜像,第一层需要一个Linux内核 比如是centos 6.8、第二层需要安装nginx、第三层安装php、第四层安装mysql5.0版本、如果有一天需要一个mysql5.5版本,可以直接把第四层替换掉,给它换成mysql5.5版本。这样的话一个镜像看起来是一个文件,其实它并不是一个文件,而是由很多很多个子文件结合起来,但也是有数目限制的,限制池为128,也就是不能够超过128层。如果新建一个有很多层级的新镜像,其中某一层和之前的镜像某一层是一样的话,则会跳过这一层,直接下载别的,这样就大大的减少了存储量(共享资源,有多个镜像都从相同的 base 镜像构建而来,那么宿主机只需在磁盘上保存一份base镜像,同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了,而且镜像的每一层都可以被共享。)实现制作镜像脚本化,同时用户可以根据自己的需要对官方镜像做扩展,或者将自己的应用打包成镜像,实现容器化部署。
1、编写一个Dockerfile 文件
2、docker build构建成为一个镜像
3、docker run 运行镜像
4、docker push 发布镜像(Docker Hub 、阿里云镜像仓库)
FROM #基础镜像,一切从这里开始构建
MAINTAINER #镜像是谁写的,名字+邮箱(新版即将废弃,被LABEL替代)
LABEL #附加到Ilmage之上的元数据,键值格式
RUN #镜像构建的时候需要运行的命令
ADD #将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget
WORKDIR #镜像的工作目录(为RUN、CMD、ENTRYPOINT、COPY和ADD等指令设定工作目录)
VOLUME #指定基于新生成的Image运行Container时期望作为Volume使用的目录
EXPOSE #指定基于新生成的Image运行Container时期望暴露的端口,但实际暴露与否取决于docker run命令的选项,支持TCP和UDP协议
CMD #指定这个容器启动的时候要运行的命令(只有最后一个会生效,可被替代)
ENTRYPOINT #类似于CMD指令的功能,指定这个容器启动的时候要运行的命令,可以追加命令,于CMD共存时,CMD的内容将作为指令中定义的程序的参数
COPY #功能类似ADD,但是不会自动解压文件,也不能访问网络资源,可复制主机上或者前一阶段构建结果中(需要使用--from选项)文件或目录生成新的镜像层
ARG #定义专用于build过程中的变量,但仅对该指标之后的调用生效,其值可由命令行选项"--build-arg"进行传递
ENV #构建的时候以键值格式设置环境变量,可被其后的指令所调用,且基于新生成的lmage运行的Container中也会存在这些变量
Dockerfile 分为四部分:基础镜像信息(FROM)、维护者信息(MAINTAINER、LABEL)、镜像操作指令(RUN、ADD、WORKDIR、VOLUME、EXPOSE、COPY、ARG、ENV)和 容器启动时执行指令 (CMD、ENTRYPOINT)。
指定基础镜像,必须为第一个命令
格式:
FROM
FROM : #不填tag默认为latest
FROM @ #digest可用于验证下载的镜像是否保证完整性,FROM node:12.18.4-alpine@sha256:757574c5a2102627de54971a0083d4ecd24eb48fdf06b234d063f19f7bbc22fb
示例:
FROM mysql:5.6
注:
tag或digest是可选的,如果不使用这两个值时,会使用latest版本的基础镜像
维护者信息
格式:
MAINTAINER
示例:
MAINTAINER pikaqiu
MAINTAINER [email protected]
MAINTAINER pikaqiu
用于为镜像添加元数据
格式:
LABEL = = = ...
示例:
LABEL version="1.0" description="这是一个Web服务器" by="pikaqiu"
注:
使用LABEL指定元数据时,一条LABEL指定可以指定一或多条元数据,指定多条元数据时不同元数据
之间通过空格分隔。推荐将所有的元数据通过一条LABEL指令指定,以免生成过多的中间镜像(因为每一个指令都会创建一个镜像层)。
指定于外界交互的端口
格式:
EXPOSE [...]
示例:
EXPOSE 80 443
EXPOSE 8080
EXPOSE 11211/tcp 11211/udp
注:EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口
如果没有暴露端口,后期也可以通过-p 8080:80方式映射端口,但是不能通过-P形式映射
容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存于卷(volume)中。
为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在 Dockerfile 中,可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。
docker容器数据卷更详细的可参考 https://www.cnblogs.com/sucretan2010/p/11014957.html
VOLUME /data
这里的 /data 目录就会在运行时自动挂载为匿名卷,任何向 /data 中写入的信息都不会记录进容器存储层,从而保证了容器存储层的无a状态化。
在容器中会自动创建/data目录
使用docker inspect 容器名可以看到/data目录挂载到了本地机器上的 /var/lib/docker/volumes/***中
运行时可以覆盖这个挂载设置,比如:
docker run -d -v mydata:/data 镜像名
# 使用了 mydata 这个命名卷挂载到了 /data 这个位置,替代了 Dockerfile 中定义的匿名卷的挂载配置
VOLUME /var/data /var/log
# 指定容器中的/var/log挂载到宿主机的/var/data目录,等同于-v /var/data:/var/log
每条 RUN 指令将在当前镜像的基础上执行指定命令,并提交为新的镜像。当命令较长时可以使用 \ 来换行,多条命令用&&来连接,避免执行多个RUN,使得镜像层数变多,最好只保留一个RUN。
RUN tar xf nginx-${nginx_ver}.tar.gz && \
yum -y install gcc pcre-devel openssl-devel make && \
cd nginx-${nginx_ver} && \
./configure && make && make install
RUN用于在构建镜像时执行命令,其有以下两种命令执行方式:
shell执行
格式:
RUN
exec执行
格式:
RUN ["executable", "param1", "param2"]
示例:
RUN apk update
RUN ["/etc/execfile", "arg1", "arg1"]
注:RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,
可以在构建时指定--no-cache参数,如:docker build --no-cache
镜像的工作目录(为RUN、CMD、ENTRYPOINT、COPY和ADD等指令设定工作目录),类似于cd命令。
格式:
WORKDIR /path/to/workdir
示例:
WORKDIR /a (这时工作目录为/a)
WORKDIR b (这时工作目录为/a/b)
WORKDIR c (这时工作目录为/a/b/c)
注:
通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY
等命令都会在该目录下执行。在使用docker run运行容器时,可以通过-w参数覆盖构建时所设置的工作目录。
将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget
格式:
ADD ...
ADD ["",... ""] 用于支持包含空格的路径
示例:
ADD hom* /mydir/ # 添加所有以"hom"开头的文件
ADD hom?.txt /mydir/ # ? 替代一个单字符,例如:"home.txt"
ADD test relativeDir/ # 添加 "test" 到 `WORKDIR`/relativeDir/
ADD test /absoluteDir/ # 添加 "test" 到 /absoluteDir/
注意:尽量别用,会增加镜像的大小,ADD 指令会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。
与ADD类似,对于压缩文件,不会自动解压
注意:不能直接拷贝目录,但可以拷贝目录下的内容,使用 COPY 指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等。
COPY config/ /opt/config/ 把当前config目录下所有文件拷贝到/opt/config/下,如果/opt/config不存在,会创建
用于指定传递给构建运行时的变量(给dockerfile传参),相当于构建镜像时可以在外部为里面传参
格式:
ARG [=]
示例:
ARG site
ARG build_user=www
From centos:7
ARG parameter
VOLUME /usr/share/nginx
RUN yum -y install $parameter
EXPOSE 80 443
CMD nginx -g "daemon off;"
# 可以如下这样灵活传参
docker build --build-arg=parameter=net-tools -t nginx:01 .
设置环境变量
格式:
#一次设置一个变量,#之后的所有内容均会被视为其的组成部分
ENV
#设置多个环境变量,每个变量为一个"="的键值对,如果中包含空格,可以使用\来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行
ENV = = \
=
示例:
ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat=fluffy myName=zhangsan
ENV DOC_ROOt=/data/web/html/ 单个文件
ENV DOC_ROOt=/data/web/html/ \ 多个文件
WEB_SERVER_PACKAGE="nginx-1.15.5"
COPY index.html ${DOC_ROOT:-/data/web/html/} # ${variable:-defaultValue} 表示如果变量值存在,就是用原来的值,否则使用默认值
COPY yum.repos.d /etc/yum.repos.d/
#ADD http://nginx.org/download/nginx-1.15.5.tar.gz /usr/local/src/
WORKDIR /usr/locl/
ADD ${WEB_SERVER_PACKAGE}.tar.gz ./src/
指定启动容器时执行的命令,每个 Dockerfile 只能有一条 CMD 命令。如果指定了多条 CMD 命令,只有
最后一条会被执行。如果用户在启动容器时指定了要运行的命令,则会覆盖掉 CMD 指定的命令。
覆盖的原因:CMD给出的是一个容器的默认的可执行体。也就是容器启动以后,默认的执行命令。重点就是这个“默认”。意味着,如果docker run没有指定任何的执行命令或者dockerfile里面也没有ENTRYPOINT,那么,就会使用CMD指定的默认的执行命令执行。同时也从侧面说明了ENTRYPOINT的含义,它才是真正的容器启动以后要执行命令。
格式:
CMD ["executable","param1","param2"] (执行可执行文件,优先)
CMD ["param1","param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)
CMD command param1 param2 (执行shell内部命令)
示例:
CMD echo "This is a test." # 这种格式,在创建容器后会首先调用Shell,即自动在命令前面追加/bin/sh -c,即上述设置将执行如下命令:/bin/sh -c echo "This is a test."
CMD ["/usr/bin/wc","--help"] # 如果你想在没有 shell 的情况下运行 ,那么必须将命令表示为 JSON 数组并提供可执行文件的完整路径。
注:CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。
配置容器启动后执行的命令,并且不会被 docker run 提供的参数覆盖(但是,docker run的**–entrypoint**可以覆盖Dockerfile中ENTRYPOINT设置的命令)。
每个 Dockerfile 中只能有一个 ENTRYPOINT,当指定多个 ENTRYPOINT 时,只有最后一个生效。
当指定了 ENTRYPOINT 后,CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令,换句话说实际执行时,将变为:
格式:
ENTRYPOINT ["executable", "param1", "param2"] (可执行文件, 优先,这种格式可追加CMD参数)
ENTRYPOINT command param1 param2 (shell内部命令,这种格式屏蔽追加任何参数)
示例:
FROM ubuntu
ENTRYPOINT ["ls", "/usr/local"]
CMD ["/usr/local/tomcat"]
之后,docker run 传递的参数,都会先覆盖cmd,然后由cmd 传递给entrypoint ,做到灵活应用
注:ENTRYPOINT与CMD非常类似,不同的是通过docker run执行的命令不会覆盖ENTRYPOINT,
而docker run命令中指定的任何参数,都会被当做参数再次传递给CMD。
Dockerfile中只允许有一个ENTRYPOINT命令,多指定时会覆盖前面的设置,
而只执行最后的ENTRYPOINT指令。
通常情况下,ENTRYPOINT 与CMD一起使用,ENTRYPOINT 写默认命令,当需要参数时候 使用CMD传参。
CMD和ENTRYPOINT的区别可参考:https://docs.docker.com/engine/reference/builder/
ENTRYPOINT&CMD
No ENTRYPOINT | ENTRYPOINT exec_entry p1_entry | ENTRYPOINT [“exec_entry”, “p1_entry”] | |
---|---|---|---|
No CMD | error, not allowed | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry |
CMD [“exec_cmd”, “p1_cmd”] | exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry exec_cmd p1_cmd |
CMD exec_cmd p1_cmd | /bin/sh -c exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd |
# git clone https://github.com/lizhenliang/tomcat-java-demo
# cd tomcat-java-demo
# vi Dockerfile
FROM maven AS build
ADD ./pom.xml pom.xml
ADD ./src src/
RUN mvn clean package
FROM lizhenliang/tomcat
RUN rm -rf /usr/local/tomcat/webapps/ROOT
COPY --from=build target/*.war /usr/local/tomcat/webapps/ROOT.war
# docker build -t demo:v1 .
# docker container run -d -v demo:v1
# 首先,第一个FROM 后边多了个 AS 关键字,可以给这个阶段起个名字。
# 然后,第二部分FROM用的我们上面构建的Tomcat镜像,COPY关键字增加了—from参数,用于拷贝某个阶段的文件到当前阶段。这样一个Dockerfile就都搞定了。
镜像制作分为两个阶段:
docker build阶段 基于dockerfile制作镜像 (RUN,用于此阶段的运行命令)
docker run阶段 基于镜像运行容器 (CMD,基于image run容器时候,需要运行的命令)
# 指定基础镜像
FROM pikaqiu/ubuntu:14.04.20161014
# 维护者信息
MAINTAINER [email protected]
# 设置环境
ENV RTMP_VERSION=1.1.10 \
NPS_VERSION=1.11.33.4 \
LIBAV_VERSION=11.8 \
NGINX_VERSION=1.10.1 \
NGINX_USER=www-data \
NGINX_SITECONF_DIR=/etc/nginx/sites-enabled \
NGINX_LOG_DIR=/var/log/nginx \
NGINX_TEMP_DIR=/var/lib/nginx \
NGINX_SETUP_DIR=/var/cache/nginx
# 设置构建时变量,镜像建立完成后就失效
ARG BUILD_LIBAV=false
ARG WITH_DEBUG=false
ARG WITH_PAGESPEED=true
ARG WITH_RTMP=true
# 复制本地文件到容器目录中
COPY setup/ ${NGINX_SETUP_DIR}/
RUN bash ${NGINX_SETUP_DIR}/install.sh
# 复制本地配置文件到容器目录中
COPY nginx.conf /etc/nginx/nginx.conf
COPY entrypoint.sh /sbin/entrypoint.sh
# 运行指令
RUN chmod 755 /sbin/entrypoint.sh
# 允许指定的端口
EXPOSE 80/tcp 443/tcp 1935/tcp
# 指定网站目录挂载点
VOLUME ["${NGINX_SITECONF_DIR}"]
ENTRYPOINT ["/sbin/entrypoint.sh"]
CMD ["/usr/sbin/nginx"]
tomcat和jdk压缩包,创建一个txt,创建一个Dockerfile目录
FROM centos:7
MAINTAINER pikaqiu
COPY readme.txt /usr/local/readme.txt
ADD jdk-8u333-linux-x64.tar.gz /usr/local/ #add命令会自动解压,解压到/usr/local/
ADD apache-tomcat-9.0.64.tar.gz /usr/local/
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
# 多个ENV最好合并为一个
ENV JAVA_HOME /usr/local/jdk1.8.0_333
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.64
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.64
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.64/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.64/logs/catalina.out
docker build -t diytomcat:1.0 .
启动生成的镜像,构建Tomcat容器
这里设置了数据卷,宿主机的/home/wjc/build/tomcat/test对应该容器的/usr/local/apache-tomcat-9.0.64/webapps/test。这样关于test项目的修复只需要在宿主机上修改就可以了,不需要进入到容器中修改。
docker run -d -p 9090:8080 --name diytomcat -v /home/wjc/build/tomcat/test:/usr/local/apache-tomcat-9.0.64/webapps/test -v /home/wjc/build/tomcat/tomcatlogs:/usr/local/apache-tomcat-9.0.64/logs diytomcat:1.0