到目前为止,已经介绍了如何启动一个简单的容器,并与之进行交互。同时也知道了如何停止、重启以及删除一个容器。接下来将展示一个Linux Web服务示例。
笔者将介绍通过docker command 以及 Dockerfile方式部署Linux Web服务。
Linux中主流的web服务有nginx、tomcat、apache、weblogic。因为笔者负责的java项目,这里web服务以tomcat为示例。
在该示例中,会使用到tomcat镜像。这个镜像会在"8888"端口启动一个相当简单为Web服务。
这一节只部署web服务,不会讲解容器共享数据卷存储、容器网络等要点,后续在做相关说明。
2. 通过docker command方式部署2.1 直接启动web容
[root@doc03 ~]# docker run -itd --name tomcat-v1.0 -p 8888:8080 tomcat Unable to find image 'tomcat:latest' locally .... Digest: sha256:a655be865e9f62d6d2ed3823c7382a2d77d0a034eb17714bbf2a514c3f620717 Status: Downloaded newer image for tomcat:latest 264ba249d3b6ce9eb0174a57f1f00cfc50f2417a30173ab3c02062815d427647
● -p
Docker物理机的端口映射到容器内,端口信息按照 "host-port:container-port"格式显示,这一点很重要
将Docker物理机的"8888"端口映射到容器内的"8080"(tomcat默认)端口。这意味着当有流量访问主机的"8888"端口的时候,流量会直接映射到容器内的"8080"端口
2.2 查看web容器运行状态
[root@doc03 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 264ba249d3b6 tomcat "catalina.sh run" 3 minutes ago Up 3 minutes 0.0.0.0:8888->8080/tcp tomcat-v1.0
当host不指名时,默认使用"0.0.0.0"所有地址
2.3 访问Web服务
获取请求本机http://$ip:8888的http状态码
[root@doc03 ~]# curl -o /dev/null -s -w %{http_code} http://10.125.7.74:8888 && echo "" 404
http状态码404一般是2种情况
● 请求的地址不存在(tomcat默认项目路径为webapps/ROOT)
● 请求的地址没有权限访问
[root@doc03 ~]# docker exec -it tomcat-v1.0 /bin/bash root@264ba249d3b6:/usr/local/tomcat# cd webapps root@264ba249d3b6:/usr/local/tomcat/webapps# ls root@264ba249d3b6:/usr/local/tomcat/webapps
发现"webapps"下没有任何项目路径
root@264ba249d3b6:/usr/local/tomcat/webapps# mkdir -pm 755 ROOT root@264ba249d3b6:/usr/local/tomcat/webapps# echo "Hi, Docker Daemon" > ROOT/index.html
创建Web首页,注意目录、文件权限
[root@doc03 ~]# curl -o /dev/null -s -w %{http_code} http://10.125.7.74:8888 200 [root@doc03 ~]# curl http://10.125.7.74:8888 Hi, Docker Daemon
http状态码为200且主页地址正常访问
笔者做过一个尝试,将"tomcat-v1.0"容器导出为镜像,再基于此镜像创建2个容器"tomcat-v1.1"、"tomcat-v1.2",启动时抛出"无法找到java环境"导致启动失败。
"export" 和 "import" 导出的是一个容器当时的快照, 不是镜像本身, 也就是说没有镜像分层(依赖镜像)。快照文件将丢弃所有的历史记录和元数据信息,例如工作目录(workdir)、启动命令(entrypoint)、历史提交信息(commit)等都会丢失。所以启动时会抛出"Neither the JAVA_HOME nor the JRE_HOME environment variable is defined"
对此笔者有个疑问,"import"的作用是什么?nginx、apache的Web服务是否会受此限制,后续试验一下。
相比于"save"、"load",最大的区别于以下四点:
● docker save 保存的是镜像(image),docker export 保存的是容器(container)
● docker load 用来载入镜像包,docker import 用来载入容器包,但两者都会恢复为镜像
● docker load 不能对载入的镜像重命名,而 docker import 可以为镜像指定新名称
● docker load 保存镜像完整记录,包含分层镜像,所以文件体积会比docker export的更大一些
3. 通过dockerfile方式部署3.1 什么是Dockerfile
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
这里仅讲解如何运行 Dockerfile 文件来定制一个镜像,具体 Dockerfile 文件内指令详解,将在下一节中介绍,这里你只要知道构建的流程即可。
3.1 简单的tomcat dockerfile镜像文件
[root@doc03 ~]# cat tomcat_dockerfile FROM tomcat MAINTAINER wangtianci<13623650548@163.com> WORKDIR /usr/local/tomcat RUN mkdir -pm 755 ./webapps/ROOT COPY ./index.html ./webapps/ROOT EXPOSE 8080 CMD ["./bin/catalina.sh", "run"] [root@doc03 ~]# cat index.html Dcoerkfile make image
● FROM
下载目标镜像,每个Dockerfile文件一行都是FORM指令,当前应用的剩余内容会作为新增镜像层添加到基础镜像层之上
● MAINTAINER
作者信息,作为镜像的元数据信息,不构建镜像
● WORKDIR
为Dockerfile中尚未执行的指令设置工作目录,该目录与镜像相关,并且会作为元数据记录到镜像配置中,但不会创建新的镜像层,笔者理解类似于家目录
● RUN
执行shell command,进入容器后执行的命令
● COPY
拷贝文件,host_file_path:container_file_path,将应用相关文件从构建上下文复制到了当前镜像中
笔者测试时 "host_file_path"文件必须与dockerfile文件在同一目录
● EXPOSE
指定容器内监听的tcp端口,作为元数据被保存下来,不会产生新的镜像层
● CMD
为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效
● 镜像分层图可以理解如下
其他参数可参考
https://www.runoob.com/docker/docker-dockerfile.html
3.3 创建镜像
[root@doc03 ~]# docker build -f /root/tomcat_dockerfile -t tomcat_dockerfile:v1 . Sending build context to Docker daemon 216.6MB Step 1/7 : FROM tomcat ---> bd431ca8553c Step 2/7 : MAINTAINER wangtianci<13623650548@163.com> ---> Running in 4683fbd16a41 Removing intermediate container 4683fbd16a41 ---> ee23a3dedb31 Step 3/7 : WORKDIR /usr/local/tomcat ---> Running in 665b3f0e6185 Removing intermediate container 665b3f0e6185 ---> d297b25ac4d8 Step 4/7 : RUN mkdir -pm 755 ./webapps/ROOT ---> Running in 055a60198fcf Removing intermediate container 055a60198fcf ---> 5a00a1e6bb7d Step 5/7 : COPY ./index.html ./webapps/ROOT ---> ceede2153756 Step 6/7 : EXPOSE 8080 ---> Running in a94bc7fcbf1b Removing intermediate container a94bc7fcbf1b ---> d89243858b42 Step 7/7 : CMD ["./bin/catalina.sh", "run"] ---> Running in 7358b3ea7e21 Removing intermediate container 7358b3ea7e21 ---> 5af688cf0cdd Successfully built 5af688cf0cdd Successfully tagged tomcat_dockerfile:v1
● -f
指明Dockerfile文件路径,可以是绝对路径或者是目标目录
● -t
制定镜像生成的标签,格式为<REPOSITORY>:<TAG>
● .
注意末尾的".",这个非常重要,一定要在目录最后包含这个"."。命令最后的"."表示Dockerfile在进行构建的时候,使用当前目录作为构建上下文
[root@doc03 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE tomcat_dockerfile v1 5af688cf0cdd 49 seconds ago 667MB tomcat_cp tomcat_v1.0 1fe040a4a939 20 hours ago 659MB tomcat latest bd431ca8553c 5 days ago 667MB [root@doc03 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 264ba249d3b6 tomcat "catalina.sh run" 20 hours ago Up 20 hours 0.0.0.0:8888->8080/tcp tomcat-v1.0
3.4 创建容器并验证
[root@doc03 ~]# docker run -d --name tomcat_dockerfile-v1.0 -p 9999:8080 tomcat_dockerfile:v1 13d20727b68c95da939416943b120e09d8b2a900e5d3bf447a9fe9e58a602f81 [root@doc03 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 13d20727b68c tomcat_dockerfile:v1 "./bin/catalina.sh r…" 3 seconds ago Up 1 second 0.0.0.0:9999->8080/tcp tomcat_dockerfile-v1.0 264ba249d3b6 tomcat "catalina.sh run" 20 hours ago Up 20 hours 0.0.0.0:8888->8080/tcp tomcat-v1.0 [root@doc03 ~]# curl http://10.125.7.74:9999 Dcoerkfile make image