Docker学习(3)-Docker镜像构建和使用

Docker学习(1)-Docker简介
Docker学习(2)-Docker基础1

Docker 镜像与制作

Docker 镜像内是否包含内核(bootfs)?

首先,从镜像的体积大小来说,一个比较小的镜像(alpine)只有几 MB,而内核文件需要一百多 MB, 因此镜像里面是没有内核的,镜像在被启动为容器后将直接使用宿主机的内核,而镜像本身则只提供相应的 rootfs,即系统正常运行所必须的用户空间的文件系统,比如/dev/,/proc,/bin,/etc 等目录,所以容器当中基本是没有/boot 目录的,而/boot 当中保存的就是与内核相关的文件和目录。
讨论论坛

Docker 镜像为什么没有提供内核?

若提供了内核,那么每个镜像的体积将至少一百 MB 以上,并且基于同一个基础镜像构建的镜像都有很大一部分冗余,容器的实质就是互相隔离的不同进程,也就是在用户空间运行的程序,而无需各自有自己的内核,共同使用主机的内
核即可。如果使用了内核,那么容器就不再是容器了,而属于虚拟机。

Docker 镜像存在的各个阶段和状态可以从下图看出:
Docker学习(3)-Docker镜像构建和使用_第1张图片
Docker 镜像构建的过程就是一层一层新增内容的过程,其中每一层及其下面的所有层都可以构建为独立的镜像
构建镜像必须有一个引用的父镜像,一般的基础镜像(父镜像)均使用 Linux 某发行版官方提供的基础镜像,该基础镜像中包含了一个 Linux 操作用户空间所需的所有命令和资源。之后的业务镜像就可以在基础镜像上一层一层的构建。

手动构建 nginx 镜像

Docker 镜像的构建类似于虚拟机的模板制作,即按照公司的实际业务需求将需要安装的软件、相关配置等基础环境配置完成,然后将虚拟机再提交为模板,最后再批量从模板批量创建新的虚拟机,这样可以极大的简化业务中相同环境的虚拟机运行环境的部署工作。Docker的镜像构建分为手动构建和自动构建(基于DockerFile),企业通常都是基于 Dockerfile 构建镜像。

手动构建镜像实际上就是在创建并运行的基础容器中安装相应的软件和配置好相应的环境,并手动提交为新的镜像。大致过程如下:

下载镜像并初始化系统

基于某个基础镜像之上重新制作 因此需要先有一个基础镜像,本次使用 官方提供的 centos 镜像为基础:

root@Docker-1:~# docker pull centos:7.7.1908
root@Docker-1:~# docker run -it centos:7.7.1908 /bin/bash
[root@dc356876188e /]# yum install wget -y
[root@c1d6bea96f0b /]# cd /etc/yum.repos.d/
[root@c1d6bea96f0b yum.repos.d]# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
[root@c1d6bea96f0b yum.repos.d]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

在容器中安装配置 nginx

[root@dc356876188e /]# yum install nginx -y
[root@dc356876188e /]# yum install -y vim pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop

关闭 nginx 默认的后台运行

[root@c1d6bea96f0b ~]# vim /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
daemon off;  # 添加该行
......

编写测试网页

[root@c1d6bea96f0b ~]# vim /usr/share/nginx/html/index.html
[root@c1d6bea96f0b ~]# cat /usr/share/nginx/html/index.html
NGINX TEST

提交为镜像

# -a 指定镜像构建者信息,-m 指定注释信息,跟上容器ID,指定镜像仓库和标签TAG
root@Docker-1:~# docker commit -a "kaivi" -m "nginx test image-1" c1d6bea96f0b nginx-1.16.1:manual-conf
sha256:5e2756b81617ad28e51f7c101ca5981594d9d865d1970e0fbca412175db89795

root@Docker-1:~# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx-1.16.1        manual-conf         5e2756b81617        24 seconds ago      459MB

从新构建的 nginx 镜像启动容器

root@Docker-1:~# docker run -it -p 8080:80  5e2756b81617 nginx
。。。 #在后端运行

root@Docker-1:~# tty
/dev/pts/1
root@Docker-1:~# ss -ntl |grep 8080
LISTEN   0         20480                     *:8080                   *:*    

访问测试

访问:http://172.20.32.101:8080/
Docker学习(3)-Docker镜像构建和使用_第2张图片

基于 Dockerfile 构建编译版 nginx 镜像

DockerFile 是一种可以被 Docker 程序解释的规格文件,DockerFile 由一条条命令组成,每条命令对应 linux 下面的一条命令,Docker 程序将这些 Dockerfile指令再翻译成真正的 linux 命令,其有自己的书写方式和支持的命令,Docker 程序读取 DockerFile 并根据指令生成 Docker 镜像,相比手动制作镜像的方式,DockerFile 更能直观的展示镜像是怎么产生的,有了写好的各种各样 DockerFile文件,当后期某个镜像有额外的需求时,只要在之前的 DockerFile 添加或者修改相应的操作即可重新生成新的 Docke 镜像,避免了重复手动制作镜像的麻烦。使用Dockerfile 构建镜像大体分为后面涉及的步骤。

一般来说,在 Dockerfile 中能够调用的命令在普通的终端中都可以调用。
一般 Dockerfile 包括以下的指令,这些指令都是放在每行的开头:
https://docs.docker.com/engine/reference/builder/#参考文献

FROM
FROM [--platform=<platform>] <image> [AS <name>]
Or
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
Or
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
# FROM 指令用于引用基础镜像(父镜像),一般该指令位于Dockerfile的第一行(#开头的注释不算),
# 但是ARG指令可以在FROM之前。

ARG
ARG <name>[=<default value>]
# ARG 指令用于声明变量,在使用docker build构建镜像时可以使用--build-arg =
# 来指定所声明的变量

RUN
# 该命令最常使用,用来运行常见的命令(在终端能用的命令其都能解析)。
# RUN 指令有两种形式来运行命令:
  # 1.使用shell运行命令:
RUN <command> :(默认使用/bin/sh -c运行该command,如果在windows则使用cmd /S /C运行该command)
  # 2. 使用可执行文件执行,该情况下不会调用shell,需要指定使用什么可执行文件来执行命令
RUN ["executable", "param1", "param2"] :(exec 形式)需要先指定一个可执行文件,再指定参数

ADD
ADD [--chown=<user>:<group>] <src>... <dest>
# ADD 指令用于向镜像添加文件或者目录,如果是打包和压缩格式(.tar.gz/.tar.xz/.tar.bz2),则
# 该命令会解压,但是(.zip)文件在添加前需要先安装unzip工具。可以指定多个源,ADD 默认将这些
# 源的路径处理为在当前构建镜像的目录中,并且彼此之间是相对路径关系。

COPY
COPY [--chown=<user>:<group>] <src>... <dest>
# COPY 指令用于复制文件到镜像,不会解压。

ENV
ENV <key> <value>
ENV <key>=<value> ...
# ENV 指令用于设置镜像启动为容器时的环境变量。

EXPOSE
EXPOSE <port> [<port>/<protocol>...]
# 该指令用于向主机暴露端口,后面直接接端口,多个用空格分隔。

LABEL
LABEL <key>=<value> <key>=<value> <key>=<value> ...
# LABEL 用于指定该镜像的作者信息。
# 如:
LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates that label-values can span multiple lines."

STOPSIGNAL
STOPSIGNAL signal
# 该指令用来设置使得容器退出的信号

USER
USER <user>[:<group>] or
USER <UID>[:<GID>]
# 用来指定在Dockerfile中的指令随后以什么身份运行,如果没有该用户,默认使用root
# 该指令一般不用

VOLUME
# 该指令用来创建一个挂载点,并标记为其挂载本地主机卷或者其它的容器卷。
VOLUME ["/data"]

WORKDIR
WORKDIR /path/to/workdir
# 为其后的RUN, CMD, ENTRYPOINT, COPY and ADD等指令设置工作文件夹,不存在则创建。

Dockerfile 的格式约定:

# Comment
INSTRUCTION arguments

Dockerfile 使用#号作为注释符,在行中间的#号不视为注释,而视为参数
INSTRUCTION Dockerfile 指令,不区分大小写,约定使用大写
arguments 每个指令的参数,最常见的就是各种常用的 linux 基础命令

另外,第一行指令必须是FROM,指定该镜像时基于哪一个父镜像构建。

# test build
FROM centos:latest
RUN ...
RUN ...

除非使用ARG指令声明的变量,导致FROM指令不在第一行

ARG  CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD  /code/run-app
...

RUN指令在 Dockerfile 中大量使用,一般用法是直接跟命令

# test build
FROM centos:latest

# 一般像下面这样使用
RUN /usr/bin/mkdir -p /usr/local/nginx/conf.d 
RUN ...

但是也可以使用下面的格式,使用列表将命令和参数传给RUN指令

# test build
FROM centos:latest

# 也可以像下面这样使用
RUN ["/bin/bash", "-c", "/usr/bin/mkdir -p /usr/local/nginx/conf.d"]
RUN ...

更详细的用法参考官方说明:

https://docs.docker.com/engine/reference/builder/#Dockerfile官方说明

https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#编写Dockerfile的最佳实践

下载 centos 基础镜像

~$ docker pull centos:7.5.1804

编辑 Dockerfile

root@Docker-1:~# cd /opt/
root@Docker-1:/opt# mkdir dockerfile/nginx -p
root@Docker-1:/opt# cd dockerfile/nginx/
root@Docker-1:/opt/dockerfile/nginx# vim Dockerfile  #生成的镜像的时候会在执行命令的当前目录查找Dockerfile 文件,所以名称不可写错,而且D必须大写
#Dcoker image for  installation of nginx
#
FROM centos:7.7.1908

LABEL maintainer="kaivi "

ENV password 123456

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 unzip

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 "kaivi Dockerfile test ..." >  /usr/local/nginx/html/index.html

EXPOSE 80 443

CMD ["/usr/local/nginx","-g","daemon off;"]
# 指定基于该镜像启动容器后容器执行的运行的命令,每个Dockerfile只能有一条,
# 如果有多条则只有最后一条被执行                                          

如果在从该镜像启动容器的时候也指定了命令,那么指定的命令会覆盖 Dockerfile构建的镜像里面的 CMD 命令,即指定的命令优先级更高,Dockerfile 的优先级较低一些。

准备源码包和配置文件

把另外编译的nginx配置文件拷贝到当前文件夹以及nginx的二进制安装包

root@Docker-1:/opt/dockerfile/nginx# cp  /etc/nginx/nginx.conf .
root@Docker-1:/opt/dockerfile/nginx# cp  /usr/local/src/nginx-1.16.1.tar.gz .
root@Docker-1:/opt/dockerfile/nginx# ll
total 1028
drwxr-xr-x 2 root root    4096 Apr 18 02:04 ./
drwxr-xr-x 3 root root    4096 Apr 18 00:26 ../
-rw-r--r-- 1 root root     816 Apr 18 01:31 Dockerfile
-rw-r--r-- 1 root root 1032630 Apr 18 01:37 nginx-1.16.1.tar.gz
-rw-r--r-- 1 root root    1482 Apr 18 02:04 nginx.conf

nginx.conf文件可以先二进制编制之后把默认的配置文件拷贝过来

构建镜像

使用docker build命令构建镜像,构建镜像时该命令需要指定 Dockerfile 和构建镜像所需要的上下文(context),这里的上下文就是构建过程需要的各种文件。
构建镜像详细说明参看: Docker-builder

# -t 选项给新镜像指定仓库和标签(REPOSITORY:TAG)
# 该种用法表示dockerd会在当前目录找需要的上下文(文件)和Dockerfile
# 也可以使用-f选项指定Dockerfile文件位置
root@Docker-1:/opt/dockerfile/nginx# docker build -t nginx:v5 .
Sending build context to Docker daemon  1.038MB
Step 1/14 : FROM centos:7.7.1908
 ---> 08d05d1d5859
Step 2/14 : LABEL maintainer="kaivi "
 ---> Using cache
 ---> ece8e70c6653
Step 3/14 : ENV password 123456
 ---> Using cache
 ---> 9ef6fa101697
Step 4/14 : RUN rpm -ivh http://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm
 ---> Using cache
 ---> 71273d2c5cf9
Step 5/14 : 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 unzip
 ---> Using cache
 ---> 6df38382d6f2
Step 6/14 : ADD nginx-1.16.1.tar.gz /usr/local/src
 ---> Using cache
 ---> ecf174bb26f0
Step 7/14 : RUN cd /usr/local/src/nginx-1.16.1 && ./configure --prefix=/usr/local/nginx --with-http_sub_module && make && make install
 ---> Using cache
 ---> 424d883a0282
Step 8/14 : RUN cd /usr/local/nginx
 ---> Using cache
 ---> 512ac72429ae
Step 9/14 : ADD nginx.conf /usr/local/nginx/conf/nginx.conf
 ---> 4bbf57ca373b
Step 10/14 : RUN useradd nginx -s /sbin/nologin
 ---> Running in a78f7495f355
Removing intermediate container a78f7495f355
 ---> 916eacfe2ae2
Step 11/14 : RUN ln -sv /usr/local/nginx/sbin/nginx  /usr/sbin/nginx
 ---> Running in 223b65d849d9
'/usr/sbin/nginx' -> '/usr/local/nginx/sbin/nginx'
Removing intermediate container 223b65d849d9
 ---> c4488baeef5e
Step 12/14 : RUN echo "kaivi Dockerfile test ..." >  /usr/local/nginx/html/index.html
 ---> Running in 640bbdd8905e
Removing intermediate container 640bbdd8905e
 ---> 91d95b58c8e1
Step 13/14 : EXPOSE 80 443
 ---> Running in 52dcea1975d1
Removing intermediate container 52dcea1975d1
 ---> 4f488f04781a
Step 14/14 : CMD ["/usr/local/nginx","-g","daemon off;"]
 ---> Running in 661dc57033ff
Removing intermediate container 661dc57033ff
 ---> 217964547b78
Successfully built 217964547b78
Successfully tagged nginx:v5
# 构建完成

使用 ARG 声明变量,在构建时指定变量值

# 使用ARG声明一个叫base_version的变量
#Dcoker image for installation of nginx
#
ARG base_version
  # 定义变量
#FROM centos:7.5.1804
FROM  ${base_version}
  # 使用变量
# 使用--build-arg 指定变量base_version的值为centos:7.7.1909
root@Docker-1:/opt/dockerfile/nginx#docker build --build-arg base_version=centos:7.7.1909 -t nginx:v5 .

查看已构建镜像

root@Docker-1:/opt/dockerfile/nginx# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               v5                  8b90ac5358a3        20 seconds ago      544MB

从构建的镜像启动容器

root@Docker-1:/opt/dockerfile/nginx# docker run -it --rm nginx:v5 /bin/bash
[root@5a536cb4b109 /]# ls 
anaconda-post.log  bin  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@5a536cb4b109 /]# pwd
/
[root@5a536cb4b109 /]# cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.2	5a536cb4b109
[root@5a536cb4b109 /]# ss -ntl
State       Recv-Q Send-Q                     Local Address:Port                                    Peer Address:Port              
[root@5a536cb4b109 /]# /usr/local/nginx/sbin/nginx 
[root@5a536cb4b109 /]# ss -ntl
State       Recv-Q Send-Q                     Local Address:Port                                    Peer Address:Port              
LISTEN      0      128                                    *:80                                                 *:*                  
[root@5a536cb4b109 /]# exit

后台启动容器

root@Docker-1:~# docker run -it -d  -p80:80 nginx:v5 /bin/bash
b0b805d0029b35392b23fc3e7803cd72f0a492ed4af01313f2533803d5b10bc2
root@Docker-1:~# ss -ntl |grep 80
LISTEN   0         20480                     *:80                     *:*     
#后面不加/bin/bash会出现container_linux.go:349的报错 

访问测试

root@Docker-1:~# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS                         NAMES
b0b805d0029b        nginx:v5            "/bin/bash"         About a minute ago   Up About a minute   443/tcp, 0.0.0.0:80->80/tcp   elegant_murdock

root@Docker-1:~# docker exec -it b0b805d0029b bash
[root@b0b805d0029b /]# cd /usr/local/nginx/html/
[root@b0b805d0029b html]# vim index.html 
[root@b0b805d0029b html]# cat index.html 
kaivi Dockerfile test ...
[root@b0b805d0029b html]# /usr/local/nginx/sbin/nginx
[root@b0b805d0029b html]# ss -ntl
State       Recv-Q Send-Q                     Local Address:Port                                    Peer Address:Port              
LISTEN      0      128                                    *:80                                                 *:*                  

访问 172.20.32.101:80
Docker学习(3)-Docker镜像构建和使用_第3张图片

在构建镜像时 Docker 启动了相应的容器

Docker 在构建镜像时,实际上启动了相应的容器,每运行一个 Dockerfile 中的指令就相当于新开了一个镜像(中间层),最后一条指令运行后会将运行的容器提交为镜像。下面就记录了不同的镜像构建时间,镜像的 ID 会不同,也就是每运行一个指令,镜像ID 就变一次。

手动构建编译版 nginx 镜像

过程为在 centos 基础 镜像之上手动编译安装 nginx ,然后再提交为镜像。

下载并初始化系统

root@Docker-1:~# docker pull centos:7.7.1908
root@Docker-1:~# docker run -it docker.io/centos:7.7.1908 /bin/bash
[root@77bb67f4452e /]# yum install wget -y
[root@77bb67f4452e /]# rm /etc/yum.repos.d/*
rm: remove regular file '/etc/yum.repos.d/CentOS-Base.repo'? y
rm: remove regular file '/etc/yum.repos.d/CentOS-CR.repo'? y
rm: remove regular file '/etc/yum.repos.d/CentOS-Debuginfo.repo'? y
rm: remove regular file '/etc/yum.repos.d/CentOS-Media.repo'? y
rm: remove regular file '/etc/yum.repos.d/CentOS-Sources.repo'? y
rm: remove regular file '/etc/yum.repos.d/CentOS-Vault.repo'? y
rm: remove regular file '/etc/yum.repos.d/CentOS-fasttrack.repo'? y
[root@77bb67f4452e /]# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
[root@77bb67f4452e /]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

在容器编译安装 nginx

[root@77bb67f4452e /]# yum install -y unzip vim gcc gcc-c++ automake lrzsz pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop
[root@77bb67f4452e /]# wget http://nginx.org/download/nginx-1.16.1.tar.gz
[root@77bb67f4452e /]# tar xvf nginx-1.16.1.tar.gz
[root@77bb67f4452e /]# cd nginx-1.16.1
[root@77bb67f4452e nginx-1.16.1]# ./configure  --prefix=/apps/nginx --with-http_sub_module
[root@77bb67f4452e nginx-1.16.1]#  make && make install

nginx 配置

关闭后台运行

[root@77bb67f4452e nginx-1.16.1]# cd /apps/nginx/
[root@77bb67f4452e nginx]# vim conf/nginx.conf
user  nginx;
worker_processes  auto;
daemon off; # 新增该行
...
[root@77bb67f4452e nginx]# ln -sv /apps/nginx/sbin/nginx /usr/sbin/nginx
'/usr/sbin/nginx' -> '/apps/nginx/sbin/nginx'

定义 html 测试界面

[root@77bb67f4452e nginx]# vim html/index.html 
<DOCTYPE html />
<head>
  <h1>Hello World Docker</h1>
</head>
<body>
  <p>This is a test...</p>
</body>       

创建用户和授权

[root@77bb67f4452e nginx]# useradd -u 2020 nginx -s /sbin/nologin 

[root@77bb67f4452e nginx]# chown nginx.nginx /apps/nginx/ -R

新开终端提交为镜像

root@Docker-1:~# tty
/dev/pts/1
root@Docker-1:~# docker commit -a "kaivi" -m "nginx test images" 77bb67f4452e nginx:vv1
sha256:07f3f714d8cb065a0be0af1fa0ca9b70f356a7f23e47bed43166c9fb0033a69f
root@Docker-1:~# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               vv1                 07f3f714d8cb        17 seconds ago      522MB
......

启动镜像

root@Docker-1:~# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               vv1                 07f3f714d8cb        17 seconds ago      522MB
nginx               v1                  66c2720f919d        28 minutes ago      544MB
nginx-1.16.1        manual-conf         5e2756b81617        10 hours ago        459MB
nginx               1.16.1              16af99d71a72        40 hours ago        127MB
alpine              latest              a187dde48cd2        3 weeks ago         5.6MB
centos              latest              470671670cac        3 months ago        237MB
centos              7.7.1908            08d05d1d5859        5 months ago        204MB
root@Docker-1:~# docker run -it -p 82:80 nginx:vv1 nginx
#最后面的 nginx 是运行的命令,即镜像里面要运行一个 nginx 命令,所以才有了前面将 
#/usr/local/nginx/sbin/nginx 软连接到 /usr/sbin/nginx ,目的就是为了让系统可以执行此命令。

访问测试查看日志

root@Docker-1:~# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS                                 NAMES
670ec45ceb99        nginx:vv1           "nginx"             About a minute ago   Up About a minute   0.0.0.0:82->80/tcp                    affectionate_kare
77bb67f4452e        centos:7.7.1908     "/bin/bash"         20 minutes ago       Up 20 minutes                                             festive_mcclintock
ea18f12e6b70        nginx:v1            "/bin/bash"         30 minutes ago       Up 30 minutes       86/tcp, 0.0.0.0:80->80/tcp, 443/tcp   cocky_saha
root@Docker-1:~# docker logs -f  670ec45ceb99
......

访问 172.20.32.101:82
Docker学习(3)-Docker镜像构建和使用_第4张图片

构建 Tomcat 业务镜像

在构建基于 tomcat 的业务镜像时,首先需要基于官方提供的 centos、debain、ubuntu、alpine 等基础镜像构建 JDK(Java 环境),然后再基于自定义的 JDK 镜像构建出业务需要的 tomcat 镜像。

构建 JDK 镜像

先基于官方提供的基础镜像,制作出安装了常用命令的自定义基础镜像,然后在基础镜像的基础之上,再制作 JDK 镜像、Tomcat 镜像等。业务镜像存放目录规整:

root@Docker-1:~# mkdir -pv /opt/dockerfile/{web/{nginx,tomcat,jdk,apache},system/{centos,ubuntu,redhat}}
mkdir: created directory '/opt/dockerfile/web'
mkdir: created directory '/opt/dockerfile/web/nginx'
mkdir: created directory '/opt/dockerfile/web/tomcat'
mkdir: created directory '/opt/dockerfile/web/jdk'
mkdir: created directory '/opt/dockerfile/web/apache'
mkdir: created directory '/opt/dockerfile/system'
mkdir: created directory '/opt/dockerfile/system/centos'
mkdir: created directory '/opt/dockerfile/system/ubuntu'
mkdir: created directory '/opt/dockerfile/system/redhat'

自定义 Centos 基础镜像

编写 Dockerfile 和构建脚本

root@Docker-1:~# docker pull centos:7.7.1908
root@Docker-1:~# cd /opt/dockerfile/system/centos
root@Docker-1:/opt/dockerfile/system/centos#vim Dockerfile
# CentOS base image , installed tools and created www user.
  
ARG base_version

FROM centos:7.7.1908

LABEL author="kaivi" \
      personal_site="www.likai.tech"

RUN rpm -ivh http://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm
        # install epel repo from aliyun.com

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
        # install basic tools for centos

RUN groupadd www -g 2022 && useradd www -u 2022 -g www
        # create www user and www group
                                           
# 构建脚本
#!/bin/bash

V="centos:7.7.1908"

docker build -t centos-base:v1 .  # 注意在当前目录构建

构建过程

root@Docker-1:/opt/dockerfile/system/centos# bash docker_build.sh 
......
Complete!
Removing intermediate container bcc5cdd3ac84
 ---> b80b6d13d6c2
Step 6/6 : RUN groupadd www -g 2022 && useradd www -u 2022 -g www
 ---> Running in cac77aefe297
Removing intermediate container cac77aefe297
 ---> 5fc2d6909f65
Successfully built 5fc2d6909f65
Successfully tagged centos-base:v1

查看构建的 centos 基础镜像

root@Docker-1:/opt/dockerfile/system/centos# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos-base         v1                  5fc2d6909f65        30 seconds ago      522MB

基于 Centos 基础镜像构建 JDK 镜像

准备 Dockerfile 文件

# JDK base image , based on centos-base:v1

FROM centos-base:v1

LABEL author="kaivi" \
      personal_site="www.likai.tech"

ADD jdk-8u241-linux-x64.tar.gz /usr/local/src

RUN ln -sv /usr/local/src/jdk1.8.0_241 /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
    # set java related env var

RUN rm -rf /etc/localtime && ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
     && echo "Asia/Shanghai" > /etc/timezone
    # set time zone to Shanghai
~                                 

准备 JDK 和 profile 文件

root@Docker-1:/opt/dockerfile/system/centos# cd  /opt/dockerfile/web/jdk/
root@Docker-1:/opt/dockerfile/web/jdk# cp /etc/profile .
root@Docker-1:/opt/dockerfile/web/jdk# vim profile 

# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).

if [ "${PS1-}" ]; then
  if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
    # The file bash.bashrc already sets the default PS1.
    # PS1='\h:\w\$ '
    if [ -f /etc/bash.bashrc ]; then
      . /etc/bash.bashrc
    fi
  else
    if [ "`id -u`" -eq 0 ]; then
      PS1='# '
    else
      PS1='$ '
    fi
  fi
fi

if [ -d /etc/profile.d ]; then
  for i in /etc/profile.d/*.sh; do
    if [ -r $i ]; then
      . $i
    fi
  done
  unset i
fi

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"

准备构建脚本

root@Docker-1:/opt/dockerfile/web/jdk# vim docker_build.sh
\root@Docker-1:/opt/dockerfile/web/jdk# cat docker_build.sh 
#!/bin/bash

docker build -t jdk-base:v8.241 .

构建

root@Docker-1:/opt/dockerfile/web/jdk# ll
total 190008
drwxr-xr-x 2 root root      4096 Apr 18 11:54 ./
drwxr-xr-x 6 root root      4096 Apr 18 10:39 ../
-rw-r--r-- 1 root root        47 Apr 18 11:36 docker_build.sh
-rw-r--r-- 1 root root       581 Apr 18 10:54 Dockerfile
-rw-r--r-- 1 root root 194545143 Apr 18 11:51 jdk-8u241-linux-x64.tar.gz
-rw-r--r-- 1 root root       732 Apr 18 11:35 profile
root@Docker-1:/opt/dockerfile/web/jdk# bash docker_build.sh 
Sending build context to Docker daemon  194.6MB
Step 1/10 : FROM centos-base:v1
 ---> 5fc2d6909f65
Step 2/10 : LABEL author="kaivi"       personal_site="www.likai.tech"
 ---> Running in 8dedfdef43ef
Removing intermediate container 8dedfdef43ef
 ---> 7d14621a9581
Step 3/10 : ADD jdk-8u241-linux-x64.tar.gz /usr/local/src
 ---> e492b88d17af
Step 4/10 : RUN ln -sv /usr/local/src/jdk1.8.0_241 /usr/local/jdk
 ---> Running in d8242b5f8036
'/usr/local/jdk' -> '/usr/local/src/jdk1.8.0_241'
Removing intermediate container d8242b5f8036
 ---> 0d3449d54998
Step 5/10 : ADD profile /etc/profile
 ---> 8ffc5ab1f947
Step 6/10 : ENV JAVA_HOME /usr/local/jdk
 ---> Running in b133b7663668
Removing intermediate container b133b7663668
 ---> 53b3e7c19b91
Step 7/10 : ENV JRE_HOME $JAVA_HOME/jre
 ---> Running in 0fbe0c83238c
Removing intermediate container 0fbe0c83238c
 ---> cee812ece223
Step 8/10 : ENV CLASSPATH $JAVA_HOME/lib:$JRE_HOME/lib
 ---> Running in c1685eccba5d
Removing intermediate container c1685eccba5d
 ---> 407f7a82f638
Step 9/10 : ENV PATH $PATH:$JAVA_HOME/bin
 ---> Running in b92f23603351
Removing intermediate container b92f23603351
 ---> 09cb81e4162a
Step 10/10 : RUN rm -rf /etc/localtime && ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime      && echo "Asia/Shanghai" > /etc/timezone
 ---> Running in 8f2a08bf7875
Removing intermediate container 8f2a08bf7875
 ---> 0bb10498e7d1
Successfully built 0bb10498e7d1
Successfully tagged jdk-base:v8.241
# 构建成功

查看构建的镜像

root@Docker-1:/opt/dockerfile/web/jdk# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
jdk-base            v8.241              0bb10498e7d1        2 minutes ago       926MB
centos-base         v1                  5fc2d6909f65        About an hour ago   522MB

启动容器进入验证 JKD 环境

root@Docker-1:~# docker run -it jdk-base:v8.241 /bin/bash
[root@1453b7367e51 /]# java -version 
java version "1.8.0_241"
Java(TM) SE Runtime Environment (build 1.8.0_241-b07)
Java HotSpot(TM) 64-Bit Server VM (build 25.241-b07, mixed mode)
[root@1453b7367e51 /]# env 
HOSTNAME=1453b7367e51
TERM=xterm
JRE_HOME=/usr/local/jdk/jre
。。。。。。
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/jdk/bin
PWD=/
JAVA_HOME=/usr/local/jdk
SHLVL=1
HOME=/root
CLASSPATH=/usr/local/jdk/lib:/usr/local/jdk/jre/lib
_=/usr/bin/env

[root@1453b7367e51 /]# ll /etc/profile  # 查看profile文件
-rw-r--r-- 1 root root 732 Apr 18 11:35 /etc/profile

[root@1453b7367e51 /]# date   # 验证时间是否同步
Sat Apr 18 11:59:41 CST 2020
[root@1453b7367e51 /]# 

root@Docker-1:~# date
Sat Apr 18 11:59:51 CST 2020

基于 JDK 镜像构建 Tomcat8 镜像

基于前面自定义的 JDK 基础镜像,构建出通用的自定义 Tomcat 基础镜像,此镜像后期会被多个业务的多个服务共同引用(这些业务的运行环境需要相同的 JDK 版本和 相同的 Tomcat 版本)。

编辑 Dockerfile

root@Docker-1:/opt/dockerfile/web/jdk# cd /opt/dockerfile/web/tomcat/
root@Docker-1:/opt/dockerfile/web/tomcat# vim Dockerfile
#  tomcat image 
  
FROM jdk-base:v8.241

LABEL author="kaivi" \
      personal_site="www.likai.tech"

        # set some env vars
ENV TZ "Asia/Shanghai"
ENV LANG en_US.UTF-8
ENV TOMCAT_MAJOR_VERSION 8
ENV TOMCAT_MINOR_VERSION 5.54
ENV CATALINA_HOME /apps/tomcat
ENV APP_DIR ${CATALINA_HOME}/webapps

        # install tomcat binary package
RUN mkdir /apps
ADD apache-tomcat-8.5.54.tar.gz /apps
RUN ln -sv /apps/apache-tomcat-8.5.54 /apps/tomcat

准备 tomcat 二进制包和构建脚本

# 上传tomcat二进制包
root@Docker-1:/opt/dockerfile/web/tomcat# rz -E
# 构建脚本
root@Docker-1:/opt/dockerfile/web/tomcat# vim docker_build.sh
#!/bin/bash

docker build -t tomcat-base:v8.5.54 .
# 加执行权限
root@Docker-1:/opt/dockerfile/web/tomcat# chmod a+x docker_build.sh 
root@Docker-1:/opt/dockerfile/web/tomcat# ll
total 10088
drwxr-xr-x 2 root root     4096 Apr 18 12:11 ./
drwxr-xr-x 6 root root     4096 Apr 18 10:39 ../
-rw-r--r-- 1 root root 10312541 Apr 18 11:46 apache-tomcat-8.5.54.tar.gz
-rwxr-xr-x 1 root root       51 Apr 18 12:11 docker_build.sh*
-rw-r--r-- 1 root root      444 Apr 18 12:09 Dockerfile

构建镜像

root@Docker-1:/opt/dockerfile/web/tomcat# ./docker_build.sh 
Sending build context to Docker daemon  10.32MB
Step 1/11 : FROM jdk-base:v8.241
 ---> 0bb10498e7d1
Step 2/11 : LABEL author="kaivi"       personal_site="www.likai.tech"
 ---> Running in af58171ff0d9
Removing intermediate container af58171ff0d9
 ---> dc4cca941fb4
Step 3/11 : ENV TZ "Asia/Shanghai"
 ---> Running in 8b745284a1c1
Removing intermediate container 8b745284a1c1
 ---> cd02c205bc5a
Step 4/11 : ENV LANG en_US.UTF-8
 ---> Running in 1b8ddfb3cb76
Removing intermediate container 1b8ddfb3cb76
 ---> 8480e037032f
Step 5/11 : ENV TOMCAT_MAJOR_VERSION 8
 ---> Running in 9147df041bce
Removing intermediate container 9147df041bce
 ---> 259e3c44b36c
Step 6/11 : ENV TOMCAT_MINOR_VERSION 5.54
 ---> Running in fde56402e295
Removing intermediate container fde56402e295
 ---> 04cde29ce6a8
Step 7/11 : ENV CATALINA_HOME /apps/tomcat
 ---> Running in 09a5df706b38
Removing intermediate container 09a5df706b38
 ---> 439b870c4b70
Step 8/11 : ENV APP_DIR ${CATALINA_HOME}/webapps
 ---> Running in 6ec66e1a64ac
Removing intermediate container 6ec66e1a64ac
 ---> 1ba75797abe6
Step 9/11 : RUN mkdir /apps
 ---> Running in 57e980c3e2cb
Removing intermediate container 57e980c3e2cb
 ---> 73000ce8f8fd
Step 10/11 : ADD apache-tomcat-8.5.54.tar.gz /apps
 ---> c5f222f366ee
Step 11/11 : RUN ln -sv /apps/apache-tomcat-8.5.54 /apps/tomcat
 ---> Running in bf3ea7a2e875
‘/apps/tomcat’ -> ‘/apps/apache-tomcat-8.5.54’
Removing intermediate container bf3ea7a2e875
 ---> ec58914afd67
Successfully built ec58914afd67
Successfully tagged tomcat-base:v8.5.54
# 构建成功

验证
查看镜像和启动为容器

root@Docker-1:/opt/dockerfile/web/tomcat# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
tomcat-base         v8.5.54             ec58914afd67        47 seconds ago      940MB
jdk-base            v8.241              0bb10498e7d1        18 minutes ago      926MB
centos-base         v1                  5fc2d6909f65        About an hour ago   522MB

root@Docker-1:/opt/dockerfile/web/tomcat# docker run -it --rm tomcat-base:v8.5.54 /bin/bash

[root@1a2873f7fc4b /]# ll /apps/tomcat/bin/catalina.sh 
-rwxr-x--- 1 root root 24397 Apr  3 22:07 /apps/tomcat/bin/catalina.sh

[root@1a2873f7fc4b /]# cd /apps/tomcat/bin/

[root@1a2873f7fc4b bin]# ./catalina.sh start
Using CATALINA_BASE:   /apps/tomcat
Using CATALINA_HOME:   /apps/tomcat
Using CATALINA_TMPDIR: /apps/tomcat/temp
Using JRE_HOME:        /usr/local/jdk/jre
Using CLASSPATH:       /apps/tomcat/bin/bootstrap.jar:/apps/tomcat/bin/tomcat-juli.jar
Tomcat started.

[root@1a2873f7fc4b bin]# ss -ntl
State       Recv-Q Send-Q             Local Address:Port                            Peer Address:Port              
LISTEN      0      1                      127.0.0.1:8005                                       *:*                  
LISTEN      0      100                            *:8080                                       *:*                  

构建业务镜像

基于前面构建的 tomcat-base 镜像构建业务镜像。分别创建 app1 和 app2 两个目录表示不同的业务项目。

业务镜像 1
准备 Dockerfile

root@Docker-1:/opt/dockerfile/web/tomcat# mkdir tomcat-{app1,app2} -pv
mkdir: created directory 'tomcat-app1'
mkdir: created directory 'tomcat-app2'
root@Docker-1:/opt/dockerfile/web/tomcat# cd tomcat-app1/
root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# pwd
/opt/dockerfile/web/tomcat/tomcat-app1

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# vim Dockerfile

# Tomcat webapp deploy image

FROM tomcat-base:v8.5.54

LABEL author="kaivi" \
      personal_site="www.likai.tech"

        # add a script to /tomcat/bin to start tomcat when container start
ADD run_tomcat.sh /apps/tomcat/bin/run_tomcat.sh

        # add business code to /tomcat/webapps/
ADD app1/* /apps/tomcat/webapps/app1/

RUN chown www.www /apps/ -R

        # expose ports
EXPOSE 8080 8005 8009

        # run tomcat when container start
CMD ["/apps/tomcat/bin/run_tomcat.sh"]

准备容器启动时启动 tomcat 的脚本

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1#  vim run_tomcat.sh
#!/bin/bash

echo "172.20.32.101 duanxin.io" >> /etc/hosts
echo "nameserver 223.6.6.6" >> /etc/resolv.conf

su - www -c "/apps/tomcat/bin/catalina.sh start"
su - www -c "tail -f /etc/hosts"

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# chmod a+x run_tomcat.sh 

编写 app1 测试页面

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# mkdir app1
root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# vim app1/index.html
<DOCTYPE HTML/>
<head>
        <h1>A TEST for Tomcat app1 <h1/>
<head/>
<body>
        <p>Tomcat app1 test...<span>NICE!<span/><p/>
<body/>

准备容器构建脚本

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# vim docker_build.sh
#!/bin/bash

docker build -t tomcat:app1 .

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# chmod a+x docker_build.sh 

构建

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# ll
total 24
drwxr-xr-x 3 root root 4096 Apr 18 12:28 ./
drwxr-xr-x 4 root root 4096 Apr 18 12:17 ../
drwxr-xr-x 2 root root 4096 Apr 18 12:26 app1/
-rwxr-xr-x 1 root root   44 Apr 18 12:28 docker_build.sh*
-rw-r--r-- 1 root root  485 Apr 18 12:20 Dockerfile
-rwxr-xr-x 1 root root  281 Apr 18 12:23 run_tomcat.sh*
root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# ./docker_build.sh 
Sending build context to Docker daemon  5.632kB
Step 1/7 : FROM tomcat-base:v8.5.54
 ---> ec58914afd67
Step 2/7 : LABEL author="kaivi"       personal_site="www.likai.tech"
 ---> Running in 44260dc1d930
Removing intermediate container 44260dc1d930
 ---> 8509c73764ec
Step 3/7 : ADD run_tomcat.sh /apps/tomcat/bin/run_tomcat.sh
 ---> 7abca622da74
Step 4/7 : ADD app1/* /apps/tomcat/webapps/app1/
 ---> d8480dca21ac
Step 5/7 : RUN chown www.www /apps/ -R
 ---> Running in 9b07147f8ddd
Removing intermediate container 9b07147f8ddd
 ---> 4024c3d41a24
Step 6/7 : EXPOSE 8080 8005 8009
 ---> Running in 21f89a17a3c0
Removing intermediate container 21f89a17a3c0
 ---> 8b0cd44d07dc
Step 7/7 : CMD ["/apps/tomcat/bin/run_tomcat.sh"]
 ---> Running in 381e94d0d825
Removing intermediate container 381e94d0d825
 ---> ca80466f5f71
Successfully built ca80466f5f71
Successfully tagged tomcat:app1
# 构建成功

从镜像启动容器

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
tomcat              app1                ca80466f5f71        33 seconds ago      954MB
tomcat-base         v8.5.54             ec58914afd67        16 minutes ago      940MB
jdk-base            v8.241              0bb10498e7d1        34 minutes ago      926MB
root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# docker run -it -d -p8080:8080 tomcat:app1 
1d3b8cbb284dd808b183e07c4f55f5c3000f7b222005d5268e4812edc9a3e497

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# ss -ntl |grep 8080
LISTEN   0         20480                     *:8080                   *:*       

访问测试

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                        NAMES
1d3b8cbb284d        tomcat:app1         "/apps/tomcat/bin/ru…"   2 minutes ago       Up 2 minutes        8005/tcp, 8009/tcp, 0.0.0.0:8080->8080/tcp   trusting_ptolemy
1453b7367e51        jdk-base:v8.241     "/bin/bash"              34 minutes ago      Up 34 minutes                                                    adoring_sutherland
ea18f12e6b70        nginx:v1            "/bin/bash"              3 hours ago         Up 3 hours          86/tcp, 0.0.0.0:80->80/tcp, 443/tcp          cocky_saha
root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# docker exec -it 1d3b8cbb284d /bin/bash

[root@1d3b8cbb284d /]# ss -ntl
State       Recv-Q Send-Q             Local Address:Port                            Peer Address:Port              
LISTEN      0      1                      127.0.0.1:8005                                       *:*                  
LISTEN      0      100                            *:8080                                       *:*           

Docker学习(3)-Docker镜像构建和使用_第5张图片
Docker学习(3)-Docker镜像构建和使用_第6张图片
业务镜像 2
准备 Dockerfile

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app2# pwd
/opt/dockerfile/web/tomcat/tomcat-app2
root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app2# vim Dockerfile 
# Tomcat webapp deploy image
  
FROM tomcat-base:v8.5.54

LABEL author="kaivi" \
      personal_site="www.likai.tech"

        # add a script to /tomcat/bin to start tomcat when container start
ADD run_tomcat.sh /apps/tomcat/bin/run_tomcat.sh

        # add business code to /tomcat/webapps/
ADD app2/* /apps/tomcat/webapps/app2/

RUN chown www.www /apps/ -R #不修改权限 后面无法写入日志导致服务启动失败

        # expose ports
EXPOSE 8080 8005 8009

        # run tomcat when container start
CMD ["/apps/tomcat/bin/run_tomcat.sh"]                                         

server.xml文件部署的时候注意关闭自动部署以及自动解压
准备容器启动时启动 tomcat 的脚本

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app2# vim run_tomcat.sh
#!/bin/bash
  
echo "172.20.32.101 duanxin.io" >> /etc/hosts
echo "nameserver 223.6.6.6" >> /etc/resolv.conf

su - www -c "/apps/tomcat/bin/catalina.sh start"
su - www -c "tail -f /etc/hosts" #创建一个守护进程,监听一个变化不大的文件

编写 app2 测试页面

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app2# mkdir app2
root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app2# vim app2/index.html
<DOCTYPE HTML/>
<head>
        <h1>A TEST for Tomcat app2 <h1/>
<head/>
<body>
        <p>Tomcat app2 test...<span>NICE!<span/><p/>
<body/>

主备容器构建脚本

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app2# vim docker_build.sh
#!/bin/bash
  
docker build -t tomcat:app2 .

构建

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app2# ./docker_build.sh 
Sending build context to Docker daemon  6.144kB
Step 1/7 : FROM tomcat-base:v8.5.54
 ---> ec58914afd67
Step 2/7 : LABEL author="kaivi"       personal_site="www.likai.tech"
 ---> Using cache
 ---> 8509c73764ec
Step 3/7 : ADD run_tomcat.sh /apps/tomcat/bin/run_tomcat.sh
 ---> b2ea0fadebfe
Step 4/7 : ADD app2/* /apps/tomcat/webapps/app2/
 ---> 2eb6ac24beae
Step 5/7 : RUN chown www.www /apps/ -R
 ---> Running in 7becf466e6a8
Removing intermediate container 7becf466e6a8
 ---> 7de7462dea98
Step 6/7 : EXPOSE 8080 8005 8009
 ---> Running in f54eeaee6b75
Removing intermediate container f54eeaee6b75
 ---> 08e605894757
Step 7/7 : CMD ["/apps/tomcat/bin/run_tomcat.sh"]
 ---> Running in 76ff5d601d03
Removing intermediate container 76ff5d601d03
 ---> 6ad29a04f9a9
Successfully built 6ad29a04f9a9
Successfully tagged tomcat:app2
# 构建成功

从镜像启动

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app2# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
tomcat              app2                6ad29a04f9a9        40 seconds ago      954MB
tomcat              app1                ca80466f5f71        3 hours ago         954MB
tomcat-base         v8.5.54             ec58914afd67        4 hours ago         940MB
jdk-base            v8.241              0bb10498e7d1        4 hours ago         926MB
centos-base         v1                  5fc2d6909f65        5 hours ago         522MB
......
root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app2# docker run -it -d -p 8081:8080 tomcat:app2
155eab9eafc871ece2b177a190077397f3744c8528ce3241e11022b52672d384
root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app2#  ss -ntl | grep 8081
LISTEN   0         20480                     *:8081                   *:*       

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app2# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                        NAMES
155eab9eafc8        tomcat:app2         "/apps/tomcat/bin/ru…"   21 seconds ago      Up 20 seconds       8005/tcp, 8009/tcp, 0.0.0.0:8081->8080/tcp   sleepy_cori
1d3b8cbb284d        tomcat:app1         "/apps/tomcat/bin/ru…"   3 hours ago         Up 3 hours          

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app2# docker exec -it 155eab9eafc8 /bin/bash
[root@155eab9eafc8 /]# ss -ntl
State       Recv-Q Send-Q             Local Address:Port                            Peer Address:Port              
LISTEN      0      1                      127.0.0.1:8005                                       *:*                  
LISTEN      0      100                            *:8080                                       *:*    

访问测试
访问 http://172.20.32.101:8081/
Docker学习(3)-Docker镜像构建和使用_第7张图片
访问 http://172.20.32.101:8081/app2/
Docker学习(3)-Docker镜像构建和使用_第8张图片

基于 alpine 和 ubuntu 构建镜像

基于 alpine 构建镜像

在基于 alpine 构建镜像时,需要注意 alpine 的一些基础命令不同于 centos 或者ubuntu 系统,主要用到的是安装软件命令apk update和apk add命令,添加用户和组的adduser和addgroup命令。

构建 alpine 基础镜像
Dockerfile

root@Docker-1:~# cd /opt/dockerfile/system/
root@Docker-1:/opt/dockerfile/system# ll
total 20
drwxr-xr-x 5 root root 4096 Apr 18 10:39 ./
drwxr-xr-x 5 root root 4096 Apr 18 10:39 ../
drwxr-xr-x 2 root root 4096 Apr 18 10:47 centos/
drwxr-xr-x 2 root root 4096 Apr 18 10:39 redhat/
drwxr-xr-x 2 root root 4096 Apr 18 10:39 ubuntu/
root@Docker-1:/opt/dockerfile/system# mkdir alpine
root@Docker-1:/opt/dockerfile/system# cd alpine/
root@Docker-1:/opt/dockerfile/system/alpine# vim Dockerfile
# A alpine base image with some tools installed
  
FROM alpine:latest

LABEL author="kaivi" \
      personal_site="www.likai.tech"
          # change the pkg source to aliyun
          # http://mirrors.aliyun.com/alpine/v3.11/main
          # http://mirrors.aliyun.com/alpine/v3.11/community
COPY repositories /etc/apk/repositories

          # install basic tools and cmd
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

更改 alpine 包源为阿里云的源
Docker学习(3)-Docker镜像构建和使用_第9张图片

root@Docker-1:/opt/dockerfile/system/alpine# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
alpine              latest              a187dde48cd2        3 weeks ago         5.6MB
......
root@Docker-1:/opt/dockerfile/system/alpine# docker run -it --rm alpine:latest sh
/ # cat /etc/apk/repositories 
http://dl-cdn.alpinelinux.org/alpine/v3.11/main
http://dl-cdn.alpinelinux.org/alpine/v3.11/community

# 替换上面的 dl-cdn.alpinelinux.org 改成 mirrors.aliyun.com

/ # vi /etc/apk/repositories 
/ # cat /etc/apk/repositories 
#http://dl-cdn.alpinelinux.org/alpine/v3.11/main
#http://dl-cdn.alpinelinux.org/alpine/v3.11/community

http://mirrors.aliyun.com/alpine/v3.11/main
http://mirrors.aliyun.com/alpine/v3.11/community

构建脚本

root@Docker-1:/opt/dockerfile/system/alpine# vim docker_build.sh 
#!/bin/bash
docker build -t alpine-base:v1 .
root@Docker-1:/opt/dockerfile/system/alpine# chmod u+x docker_build.sh 

构建和查看
构建

root@Docker-1:/opt/dockerfile/system/alpine# ./docker_build.sh 
Sending build context to Docker daemon  1.038MB
Step 1/4 : FROM alpine:latest
 ---> a187dde48cd2
Step 2/4 : LABEL author="kaivi"       personal_site="www.likai.tech"
 ---> Using cache
 ---> 0580a9d9e882
Step 3/4 : COPY repositories /etc/apk/repositories
 ---> Using cache
 ---> 9fc2e55e1e26
Step 4/4 : 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
 ---> Running in d2b8e2724ac2
fetch http://mirrors.aliyun.com/alpine/v3.11/main/x86_64/APKINDEX.tar.gz
fetch http://mirrors.aliyun.com/alpine/v3.11/community/x86_64/APKINDEX.tar.gz
v3.11.5-56-gd94bd50429 [http://mirrors.aliyun.com/alpine/v3.11/main]
v3.11.5-54-g70c5111c08 [http://mirrors.aliyun.com/alpine/v3.11/community]
OK: 11271 distinct packages available
(1/48) Installing libgcc (9.2.0-r4)
(2/48) Installing libstdc++ (9.2.0-r4)
(3/48) Installing binutils (2.33.1-r0)
......
(47/48) Installing zip (3.0-r7)
(48/48) Installing zlib-dev (1.2.11-r3)
Executing busybox-1.31.1-r9.trigger
Executing ca-certificates-20191127-r1.trigger
OK: 183 MiB in 62 packages
Removing intermediate container d2b8e2724ac2
 ---> 644eb1be20b8
Successfully built 644eb1be20b8
Successfully tagged alpine-base:v1
# 构建完成
root@Docker-1:/opt/dockerfile/system/alpine# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
alpine-base         v1                  644eb1be20b8        24 seconds ago      180MB
......

root@Docker-1:/opt/dockerfile/system/alpine# docker run --rm -it alpine-base:v1 /bin/sh
/ # ping 114.114.114.114
PING 114.114.114.114 (114.114.114.114): 56 data bytes
64 bytes from 114.114.114.114: seq=0 ttl=127 time=15.745 ms
64 bytes from 114.114.114.114: seq=1 ttl=127 time=16.932 ms
^C
--- 114.114.114.114 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 15.745/16.338/16.932 ms
/ # ping www.baidu.com
PING www.baidu.com (61.135.169.121): 56 data bytes
64 bytes from 61.135.169.121: seq=0 ttl=127 time=3.724 ms
^C
--- www.baidu.com ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 3.724/3.724/3.724 ms
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:06  
          inet addr:172.17.0.6  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:18 errors:0 dropped:0 overruns:0 frame:0
          TX packets:19 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:1708 (1.6 KiB)  TX bytes:1625 (1.5 KiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
/ # apk update # 查看阿里云的源是否成功生效
fetch http://mirrors.aliyun.com/alpine/v3.11/main/x86_64/APKINDEX.tar.gz`在这里插入代码片`
fetch http://mirrors.aliyun.com/alpine/v3.11/community/x86_64/APKINDEX.tar.gz
v3.11.5-56-gd94bd50429 [http://mirrors.aliyun.com/alpine/v3.11/main]
v3.11.5-54-g70c5111c08 [http://mirrors.aliyun.com/alpine/v3.11/community]
OK: 11271 distinct packages available

基于 alpine 基础镜像构建 nginx 镜像

Dockerfile

root@Docker-1:/opt/dockerfile/system/alpine# mkdir nginx
root@Docker-1:/opt/dockerfile/system/alpine# vim nginx/Dockerfile 
#nginx base image , based on alpine-base:v1
FROM alpine-base:v1

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/nginx

RUN addgroup -g 2020 -S nginx && adduser -s /sbin/nologin -S -D -u 2020 -G nginx nginx

COPY nginx.conf /apps/nginx/conf/nginx.conf

ADD Development_code.tar.gz /data/nginx/html

RUN chown nginx.nginx /data/nginx/ /apps/nginx/ -R

EXPOSE 80 443

CMD ["/apps/nginx"]

构建脚本

root@Docker-1:/opt/dockerfile/system/alpine# cd nginx/
root@Docker-1:/opt/dockerfile/system/alpine/nginx# vim docker_build.sh 
#!/bin/bash
docker build -t nginx-alpine:v1 .

root@Docker-1:/opt/dockerfile/system/alpine/nginx# chmod u+x docker_build.sh 

构建上下文准备

root@Docker-1:/opt/dockerfile/system/alpine/nginx# rz -E #上传nginx二进制安装包
root@Docker-1:/opt/dockerfile/system/alpine/nginx# mkdir Development_code

# 测试界面
root@Docker-1:/opt/dockerfile/system/alpine/nginx# vim Development_code/index.html
<DOCTYPE HTML/>
<head>
        <h1>A TEST for alpine... <h1/>
<head/>
<body>
        <p>Based alpine\'s nginx deployment.<span>wa...<span/><p/>
<body/>
root@Docker-1:/opt/dockerfile/system/alpine/nginx# tar -cvf Development_code.tar.gz Development_code/*
Development_code/index.html

root@Docker-1:/opt/dockerfile/system/alpine/nginx# cp /usr/local/src/nginx-1.16.1/conf/nginx.conf .

root@Docker-1:/opt/dockerfile/system/alpine/nginx# ll
total 1048
drwxr-xr-x 3 root root    4096 Apr 18 16:47 ./
drwxr-xr-x 3 root root    4096 Apr 18 16:36 ../
drwxr-xr-x 2 root root    4096 Apr 18 16:43 Development_code/
-rw-r--r-- 1 root root   10240 Apr 18 16:46 Development_code.tar.gz
-rwxr--r-- 1 root root      46 Apr 18 16:38 docker_build.sh*
-rw-r--r-- 1 root root     504 Apr 18 16:36 Dockerfile
-rw-r--r-- 1 root root 1032630 Apr 18 01:37 nginx-1.16.1.tar.gz
-rw-r--r-- 1 root root    2656 Apr 18 16:47 nginx.conf

nginx 配置

root@Docker-1:/opt/dockerfile/system/alpine/nginx# vim nginx.conf 
...
user  nginx;
daemon off;
...
http {
  ...
    server {
        listen       80;
        server_name  localhost;
        access_log  logs/host.access.log  main;
        location / {
            root   /data/nginx/html;
            index  index.html index.htm;
        }
        ...
    }
    ...
}

构建

root@Docker-1:/opt/dockerfile/system/alpine/nginx# ./docker_build.sh 
Sending build context to Docker daemon  1.052MB
Step 1/9 : FROM alpine-base:v1
 ---> 644eb1be20b8
Step 2/9 : ADD nginx-1.16.1.tar.gz /opt/
 ---> Using cache
 ---> 02a9d885ce4a
Step 3/9 : RUN cd /opt/nginx-1.16.1 && ./configure --prefix=/apps/nginx && make && make install && ln -sv /apps/nginx/sbin/nginx /usr/bin/nginx
 ---> Using cache
 ---> 8d2e969ada82
Step 4/9 : RUN addgroup -g 2020 -S nginx && adduser -s /sbin/nologin -S -D -u 2020 -G nginx nginx
 ---> Using cache
 ---> 8f1bde17d483
Step 5/9 : COPY nginx.conf /apps/nginx/conf/nginx.conf
 ---> Using cache
 ---> 8ad0f6605500
Step 6/9 : ADD Development_code.tar.gz /data/nginx/html
 ---> Using cache
 ---> 47d4407df50c
Step 7/9 : RUN chown nginx.nginx /data/nginx/ /apps/nginx/ -R
 ---> Using cache
 ---> d5ec7aceeb8e
Step 8/9 : EXPOSE 80 443
 ---> Using cache
 ---> 51233e047af8
Step 9/9 : CMD ["/apps/nginx"]
 ---> Using cache
 ---> 3fc77202b016
Successfully built 3fc77202b016
Successfully tagged nginx-alpine:v1

访问测试

root@Docker-1:~# cd /opt/dockerfile/system/alpine/nginx/
root@Docker-1:/opt/dockerfile/system/alpine/nginx# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx-alpine        v1                  3fc77202b016        45 seconds ago      209MB
alpine-base         v1                  644eb1be20b8        22 minutes ago      180MB

root@Docker-1:/opt/dockerfile/system/alpine/nginx# docker run -it -p 80:80 nginx-alpine:v1 tail -f /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.2	83c8c4f7ee36
root@Docker-1:/opt/dockerfile/system/alpine/nginx# docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                         NAMES
83c8c4f7ee36        nginx-alpine:v1     "tail -f /etc/hosts"   About an hour ago   Up About an hour    0.0.0.0:80->80/tcp, 443/tcp   practical_tereshkova
root@Docker-1:/opt/dockerfile/system/alpine/nginx# docker exec -it 83c8c4f7ee36 sh
/ # /apps/nginx/sbin/nginx  #在容器中启动nginx
......

访问http://172.20.32.101/,由于根下没有 index.html 所以无法访问
Docker学习(3)-Docker镜像构建和使用_第10张图片
访问http://172.20.32.101/Development_code/ 成功访问
Docker学习(3)-Docker镜像构建和使用_第11张图片

基于 ubuntu 构建镜像

基于 ubuntu 构建镜像与其他系统大同小异

构建 ubuntu 基础镜像
Dockerfile

root@Docker-1:/opt/dockerfile/system/ubuntu# pwd
/opt/dockerfile/system/ubuntu
root@Docker-1:/opt/dockerfile/system/ubuntu# vim Dockerfile
# ubuntu base image with some tools installed

FROM ubuntu:latest

LABEL author="kaivi" \
      personal_site="www.likai.tech"

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

sources.list

root@Docker-1:/opt/dockerfile/system/ubuntu# vim sources.list 

deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse

构建

root@Docker-1:/opt/dockerfile/system/ubuntu# vim docker_build.sh 

#!/bin/bash
docker build -t ubuntu-base:v1 .

root@Docker-1:/opt/dockerfile/system/ubuntu# chmod u+x docker_build.sh 

root@Docker-1:/opt/dockerfile/system/ubuntu# ll
total 20
drwxr-xr-x 2 root root 4096 Apr 18 18:29 ./
drwxr-xr-x 6 root root 4096 Apr 18 16:11 ../
-rwxr--r-- 1 root root   45 Apr 18 18:24 docker_build.sh*
-rw-r--r-- 1 root root  573 Apr 18 18:21 Dockerfile
-rw-r--r-- 1 root root  907 Apr 18 18:23 sources.list

#构建镜像
root@Docker-1:/opt/dockerfile/system/ubuntu# ./docker_build.sh 
Sending build context to Docker daemon   5.12kB
Step 1/4 : FROM ubuntu:latest
 ---> 4e5021d210f6
Step 2/4 : LABEL author="kaivi"       personal_site="www.likai.tech"
 ---> Using cache
 ---> a127319deb66
Step 3/4 : COPY sources.list /etc/apt/sources.list
 ---> Using cache
 ---> e6180393cf90
Step 4/4 : 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
 ---> Using cache
 ---> 060ffdc4bf27
Successfully built 060ffdc4bf27
Successfully tagged ubuntu-base:v1
# 构建完成
注意:
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
  # 该警告意思是apt的命令行接口不稳定,慎用

#查看构建完成的镜像
root@Docker-1:/opt/dockerfile/system/ubuntu# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu-base         v1                  060ffdc4bf27        5 minutes ago       366MB
......

基于 ubuntu 基础镜像构建 nginx 镜像

Dockerfile

root@Docker-1:/opt/dockerfile/system/ubuntu# mkdir nginx
root@Docker-1:/opt/dockerfile/system/ubuntu# cd nginx/

root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# vim Dockerfile
# A nginx image based on ubuntu

FROM ubuntu-base:v1

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 Development_code.tar.gz /data/nginx/html

RUN groupadd -g 2021 nginx && \
    useradd -g nginx -s /usr/sbin/nologin -u 2021 nginx && \
    chown -R nginx.nginx /apps/nginx /data/nginx

EXPOSE 80 443

CMD ["/apps/nginx"]

构建

root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# vim docker_build.sh
#!/bin/bash
docker build -t nginx-ubuntu:v1 .

root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# chmod u+x docker_build.sh 

由于和之前的alpine的nginx构建基本差不多。直接复用即可

root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# cp /opt/dockerfile/system/alpine/nginx/nginx.conf .
root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# cp /opt/dockerfile/system/alpine/nginx/nginx-1.16.1.tar.gz .
root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# cp /opt/dockerfile/system/alpine/nginx/Development_code.tar.gz .

#修改测试界面

```bash
root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# tar xf Development_code.tar.gz 
root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# vim Development_code/index.html 
<DOCTYPE HTML/>
<head>
        <h1>A TEST for Ubuntu... <h1/>
<head/>
<body>
        <p>Based ubuntu\'s nginx deployment.<span>wa o ...<span/><p/>
<body/>

root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# tar cvf Development_code.tar.gz Development_code/*
Development_code/index.html

root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# rm -rf Development_code*
root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# ll
total 1044
drwxr-xr-x 2 root root    4096 Apr 18 18:49 ./
drwxr-xr-x 3 root root    4096 Apr 18 18:33 ../
-rwxr--r-- 1 root root      45 Apr 18 18:37 docker_build.sh*
-rw-r--r-- 1 root root     606 Apr 18 18:36 Dockerfile
-rw-r--r-- 1 root root 1032630 Apr 18 18:40 nginx-1.16.1.tar.gz
-rw-r--r-- 1 root root    2664 Apr 18 18:39 nginx.conf
-rw-r--r-- 1 root root   10240 Apr 18 18:49 Development_code.tar.gz

# 构建
root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# ./docker_build.sh 
Sending build context to Docker daemon  1.051MB
Step 1/8 : FROM ubuntu-base:v1
 ---> 060ffdc4bf27
Step 2/8 : ADD nginx-1.16.1.tar.gz /usr/local/src
 ---> Using cache
 ---> 4fdc3572f0e4
Step 3/8 : 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
 ---> Using cache
 ---> aa96d2e91820
Step 4/8 : ADD nginx.conf /apps/nginx/conf/nginx.conf
 ---> Using cache
 ---> b55a1aca5867
Step 5/8 : ADD Development_code.tar.gz /data/nginx/html
 ---> Using cache
 ---> 7d3df02bae55
Step 6/8 : RUN groupadd -g 2021 nginx &&     useradd -g nginx -s /usr/sbin/nologin -u 2021 nginx &&     chown -R nginx.nginx /apps/nginx /data/nginx
 ---> Using cache
 ---> 4c09408b97e5
Step 7/8 : EXPOSE 80 443
 ---> Using cache
 ---> 41c1567c685e
Step 8/8 : CMD ["/apps/nginx"]
 ---> Using cache
 ---> d42a1310db5e
Successfully built d42a1310db5e
Successfully tagged nginx-ubuntu:v1
# 构建完成   

访问测试

root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
nginx-ubuntu         v1                  d42a1310db5e        About a minute ago   382MB
ubuntu-base         v1                  060ffdc4bf27        26 minutes ago       366MB

root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# docker run -it -d -p 80:80 nginx-ubuntu:v1 /bin/bash
c0a7a0b31bf6d50f59860ad189f8ebfc297d69bbbc1f56ed40ed476e65eb9ff3

root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# lsof -i:80
COMMAND     PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
docker-pr 49074 root    4u  IPv6 458003      0t0  TCP *:http (LISTEN)

访问http://172.20.32.101/
访问现象和基于 alpine 时一样,由于根下没有 index.html 所以无法访问
Docker学习(3)-Docker镜像构建和使用_第12张图片
Docker学习(3)-Docker镜像构建和使用_第13张图片

构建 HAProxy 镜像

基于 centos-base 镜像构建 haproxy 镜像,将 haproxy 通过容器的方式运行
http://download.openpkg.org/components/cache/haproxy/#haproxy下载

准备 Dockerfile

root@Docker-1:~# cd /opt/dockerfile/system/centos/
root@Docker-1:/opt/dockerfile/system/centos# mkdir haproxy
root@Docker-1:/opt/dockerfile/system/centos# cd haproxy/

root@Docker-1:/opt/dockerfile/system/centos/haproxy# vim Dockerfile
# A HAProxy image based on centos-base:v1 with some tools installed
FROM centos-base:v1         

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.5.tar.gz /usr/local/src/

RUN cd /usr/local/src/haproxy-2.0.5 && \
    make ARCH=x86_64 TARGET=linux-glibc 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 #80用于访问 9999用于监听

CMD ["/usr/bin/run_haproxy.sh"]
                                 

准备 HAProxy 源码和配置

http://www.haproxy.org/download/2.0/src/haproxy-2.0.5.tar.gz#国外下载地址 需要科学上网

root@Docker-1:/opt/dockerfile/system/centos/haproxy# rz -E

# 编辑haproxy配置文件
root@Docker-1:/opt/dockerfile/system/centos/haproxy# 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  docker_test_run
 bind 0.0.0.0:80
 mode http
 log global
 balance roundrobin
 server web1  172.20.32.101:8080  check inter 3000 fall 2 rise 5
 server web2  172.20.32.102:8080  check inter 3000 fall 2 rise 5

准备镜像构建脚本

root@Docker-1:/opt/dockerfile/system/centos/haproxy# vim run_haproxy.sh
#!/bin/bash
/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg
tail -f /etc/hosts

# 加执行权限
root@Docker-1:/opt/dockerfile/system/centos/haproxy# chmod u+x run_haproxy.sh 

# 编辑构建脚本
root@Docker-1:/opt/dockerfile/system/centos/haproxy# vim docker_build.sh
#!/bin/bash
docker build -t haproxy-ubuntu:v1 .

# 加执行权限
root@Docker-1:/opt/dockerfile/system/centos/haproxy# chmod u+x docker_build.sh 

root@Docker-1:/opt/dockerfile/system/centos/haproxy# ll
total 2504
drwxr-xr-x 2 root root    4096 Apr 18 20:24 ./
drwxr-xr-x 3 root root    4096 Apr 18 19:19 ../
-rwxr--r-- 1 root root      48 Apr 18 20:24 docker_build.sh*
-rw-r--r-- 1 root root     760 Apr 18 20:15 Dockerfile
-rw-r--r-- 1 root root 2539226 Apr 18 20:13 haproxy-2.0.5.tar.gz
-rw-r--r-- 1 root root     680 Apr 18 20:20 haproxy.cfg
-rwxr--r-- 1 root root      77 Apr 18 20:22 run_haproxy.sh*

#构建
root@Docker-1:/opt/dockerfile/system/centos/haproxy# ./docker_build.sh 
Sending build context to Docker daemon  2.546MB
Step 1/8 : FROM centos-base:v1
 ---> 5fc2d6909f65
Step 2/8 : 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
 ---> Using cache
 ---> 57ffe53d1e8c
Step 3/8 : ADD haproxy-2.0.5.tar.gz /usr/local/src/
 ---> Using cache
 ---> 482118c25cb7
Step 4/8 : RUN cd /usr/local/src/haproxy-2.0.5 &&     make ARCH=x86_64 TARGET=linux-glibc 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
 ---> Using cache
 ---> de502b965fdd
Step 5/8 : ADD haproxy.cfg /etc/haproxy/
 ---> Using cache
 ---> 336162d98639
Step 6/8 : ADD run_haproxy.sh /usr/bin
 ---> Using cache
 ---> 8c2012534b01
Step 7/8 : EXPOSE 80 9999
 ---> Using cache
 ---> 6c59694b7da0
Step 8/8 : CMD ["/usr/bin/run_haproxy.sh"]
 ---> Using cache
 ---> 47b597b9cb7c
Successfully built 47b597b9cb7c
Successfully tagged haproxy-ubuntu:v1

从镜像启动容器

root@Docker-1:/opt/dockerfile/system/centos/haproxy# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
haproxy-ubuntu      v1                  47b597b9cb7c        55 seconds ago      787MB
......
root@Docker-1:/opt/dockerfile/system/centos/haproxy# docker run -it -p 80:80 -p 9999:9999 haproxy-ubuntu:v1 bash
[root@e5e34e1bf06a /]# haproxy -f /etc/haproxy/haproxy.cfg 
[root@e5e34e1bf06a /]# 
[root@e5e34e1bf06a /]# ss -ntl
State       Recv-Q Send-Q             Local Address:Port                            Peer Address:Port              
LISTEN      0      128                            *:9999                                       *:*                  
LISTEN      0      128                            *:80                                         *:*                  
[root@e5e34e1bf06a /]# 

Docker学习(3)-Docker镜像构建和使用_第14张图片
后端的web1和web2现在处于down状态:
Docker学习(3)-Docker镜像构建和使用_第15张图片

由于在Dockerfile配置中有ADD haproxy.cfg /etc/haproxy/ 会自动起来这个haproxy服务 所以在最后面不需要加bash也可以

root@Docker-1:/opt/dockerfile/system/centos/haproxy# docker run -it -p 80:80 -p 9999:9999 haproxy-ubuntu:v1 
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.2	79ce10f0b3c8

启动后端服务

在后端服务器172.20.32.101机器部署(本机)

root@Docker-1:~# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
haproxy-ubuntu      v1                  47b597b9cb7c        2 hours ago         787MB
nginx-ubuntu        v1                  d42a1310db5e        4 hours ago         382MB
ubuntu-base         v1                  060ffdc4bf27        4 hours ago         366MB
tomcat              app2                6ad29a04f9a9        7 hours ago         954MB
tomcat              app1                ca80466f5f71        10 hours ago        954MB

root@Docker-1:~# docker run -d -it -p 8080:8080 tomcat:app1  
180b61179821490e795d9300135003a73dfc87b0fa3d69ae3a638aaad7753ed8
root@Docker-1:~# ss -ntl
......
LISTEN        0              20480                                *:9999                              *:*            
LISTEN        0              20480                                *:8080                              *:*            
LISTEN        0              20480                                *:80                                *:*      
......

Docker学习(3)-Docker镜像构建和使用_第16张图片
将 tomcat:app2部署到 172.20.32.102
172.20.32.101上面导出tomcat业务镜像,拷贝到172.20.32.102使用

root@Docker-1:~# docker save tomcat:app2 > /opt/tomcat:app2.tar.gz  

root@Docker-1:~# scp /opt/tomcat\:app2.tar.gz 172.20.32.102:/opt/tomcat\:app2.tar.gz
#这里可能需要一些时间

在172.20.32.102导入镜像

root@Docker-2:~# docker load < /opt/tomcat\:app2.tar.gz 
51505ea32d5f: Loading layer [==================================================>]  24.27MB/24.27MB
0c747fb19e38: Loading layer [==================================================>]  299.4MB/299.4MB
27853411f83c: Loading layer [==================================================>]  742.9kB/742.9kB
8ee048c0d621: Loading layer [==================================================>]  404.9MB/404.9MB
9866565c322a: Loading layer [==================================================>]   2.56kB/2.56kB
15567403b930: Loading layer [==================================================>]  3.072kB/3.072kB
4032e44635ce: Loading layer [==================================================>]  3.072kB/3.072kB
30dc82522c0e: Loading layer [==================================================>]  2.048kB/2.048kB
8eeeba765392: Loading layer [==================================================>]     15MB/15MB
3b202fd39753: Loading layer [==================================================>]  2.048kB/2.048kB
cd65936fedb7: Loading layer [==================================================>]  3.584kB/3.584kB
8e94fe36ca9f: Loading layer [==================================================>]  4.608kB/4.608kB
f7afa4a062d8: Loading layer [==================================================>]     15MB/15MB
Loaded image: tomcat:app2

root@Docker-2:~# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
tomcat              app2                6ad29a04f9a9        7 hours ago         954MB
nginx               1.16.1              16af99d71a72        2 days ago          127MB
centos              7.7.1908            08d05d1d5859        5 months ago        204MB
root@Docker-2:~# docker run -d -it -p 8080:8080 tomcat:app2  
4e6ebc86b7b51d6ab8c87aaf8a669dc5f6edd2c94d2470451389ca3ed840b84a
root@Docker-2:~# ss -ntl
State         Recv-Q         Send-Q                   Local Address:Port                   Peer Address:Port         
LISTEN        0              511                            0.0.0.0:80                          0.0.0.0:*            
LISTEN        0              128                      127.0.0.53%lo:53                          0.0.0.0:*            
LISTEN        0              128                            0.0.0.0:22                          0.0.0.0:*            
LISTEN        0              128                          127.0.0.1:6010                        0.0.0.0:*            
LISTEN        0              128                          127.0.0.1:6011                        0.0.0.0:*            
LISTEN        0              20480                                *:8080                              *:*            
LISTEN        0              511                               [::]:80                             [::]:*            
LISTEN        0              128                               [::]:22                             [::]:*            
LISTEN        0              128                              [::1]:6010                           [::]:*            
LISTEN        0              128                              [::1]:6011                           [::]:*   

两台后端服务都启动后,控制界面 web1 和 web2 都是 UP 状态
访问:http://172.20.32.101:9999/haproxy-status
Docker学习(3)-Docker镜像构建和使用_第17张图片

访问验证

访问web
单独访问:http://172.20.32.101:8080/app1/
Docker学习(3)-Docker镜像构建和使用_第18张图片
单独访问:http://172.20.32.102:8080/app2/
Docker学习(3)-Docker镜像构建和使用_第19张图片
访问 haproxy
1.访问:http://172.20.32.101/
Docker学习(3)-Docker镜像构建和使用_第20张图片

2.访问:http://172.20.32.101/app1/
Docker学习(3)-Docker镜像构建和使用_第21张图片
3.访问:http://172.20.32.101/app1/
Docker学习(3)-Docker镜像构建和使用_第22张图片
4.访问:http://172.20.32.101/app2/
Docker学习(3)-Docker镜像构建和使用_第23张图片
5.同理,刷新之后调度到另外一台tomcat上面,但是另外一台上面没有/app2/的数据
Docker学习(3)-Docker镜像构建和使用_第24张图片
访问控制端
Docker学习(3)-Docker镜像构建和使用_第25张图片

你可能感兴趣的:(docker学习,Dockerfile)