dockers01

1.Docker镜像制作和管理

1.1 Docker 镜像说明

1.1.1 docker 镜像中没有内核

从镜像大小上面说,一个比较小的镜像只有1MB多点,或几MB,而内核文件需要几十个MB因此镜像里面是没有内核的,镜像在被启动为容器后将直接使用宿主机内核,而镜像本身则只是提供相应的rootfs(跟文件管理系统) ,也就是系统正常运行的必须是用户空间的文件系统,比如:/dev/,/proc/,/bin/ ,/etc./ 等目录, 容器当中/boot 目录是空的,而/boot 当中保存的就是与内核相关的文件和目录。

root@Ubuntu1804-101:~# docker run -it centos bash 
[root@2a49b22a8fed /]# cd /boot/
bash: cd: /boot/: No such file or directory
[root@2a49b22a8fed /]#

1.1.2 为什么没有内核

由于容器启动和运行过程中直接使用了宿主机的内核,不会直接调用物理硬核,所以也不会设计到硬件驱动,因此也无需容器内拥有自己的内核和驱动,而如果会虚拟机技术,对应每个虚拟机都有自己独立的内核、

1.1.3 容器中的程序后台运行会导致此容器启动后会立即退出

Docker容器如果希望启动后能持续运行,就必须有一个能前台持续运行的进程,如果在容器中启动传统的服务,如:httpd,php-fpm等均为后台进程模式运行,就导致 docker 在前台没有运行的应用,这样的容器启动后会立即退出。所以一般会将服务程序以前台方式运行,对于有一些可能不知道怎么实现前台运行的程序,只需要在你启动的该程序之后添加类似于 tail ,top 这种可以前台运行的程序即可. 比较常用的方法,如 tail -f /etc/hosts 。

#httpd
ENTRYPOINT [ "/usr/sbin/apache2" ]  
CMD ["-D", "FOREGROUND"]  

#nginx
ENTRYPOINT [ "/usr/sbin/nginx", "-g", "daemon off;" ]  

#用脚本运行容器
cat run_haproxy.sh
#!/bin/bash
haproxy -f /etc/haproxy/haproxy.cfg
tail -f /etc/hosts
tail -n1 Dockerfile
CMD ["run_haproxy.sh"]

1.1.4 docker 镜像生命周期

image-20211128195515155

1.1.5 制作镜像方式

Docker 镜像制作类似类似于虚拟机的镜像(模式)制作,即按照公司的实际业务需求将需要安装的软件,相关配置等基础环境配置完成,然后将其做成镜像,最后再批量从镜像批量生成容器实例,这样可以极大的简化相同环境的部署工作,

Docker 的镜像制作分为手动制作(基于容器)和自动制作(基于dockerfile)企业通常都是基于Docker 制作镜像

docker commit #通过修改现有容器,将之手动构建为镜像
docker build #通过docker 文件,批量构建为镜像。

1.2 将现有容器通过docker commit 手动构建镜像

1.2.1 基于容器手动制作镜像步骤

docker commit 格式

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
#选项
-a, --author string   Author (e.g., "John Hannibal Smith <hannibal@ateam.com作者(例如,“约翰·汉尼拔·史密斯<hannibal@ateam.com>”)  

-c, --change list     Apply Dockerfile instruction to the created image 对创建的映像应用Dockerfile指令  
-m, --message string   Commit message 提交消息 可以添加我这次做镜像 做了那些修改
-p, --pause           Pause container during commit (default true)在提交期间暂停容器(默认为true)
#说明:
制作镜像和CONTAINER状态无关,停止状态也可以制作镜像 运行的容器和停止的运行容器都是可以制作镜像的
如果没有指定[REPOSITORY[:TAG]],REPOSITORY和TAG都为<none>
提交的时候标记TAG号: 生产当中常用,后期可以根据TAG标记创建不同版本的镜像以及创建不同版本的容器

基于容器手动制作镜像步骤具体如下:

  1. 下载一个系统的官方镜像(基础镜像),如Centos 或者 Ubuntu

  2. 基于基础镜像启动一个容器,并进入到容器

  3. 在容器里面做配置操作

    • 安装基础命令

    • 配置运行环境

    • 安装服务和配置服务

    • 放业务长须代码

  4. 提交为一个新的镜像docker commit

  5. 基于自己的镜像创建容器并测试

1.2.2 实战案例:基于busybox 制作httpd 镜像

[root@ubuntu1804 ~]#docker run -it --name b1 busybox 
/ # ls
bin   dev   etc   home proc root sys   tmp   usr   var
/ # echo httpd website in busybox >index.html
/ # httpd -f
#访问测试
root@Ubuntu1804-101:~# curl 172.17.0.2
httpd website in busybox
#或者
/ # mkdir /data/html -p
/ # echo hhhh > /data/html/index.html
/ # cat /data/html/index.html
hhhh
/ # httpd -h /data/html/
#访问测试


/ # httpd --help
BusyBox v1.32.0 (2020-06-27 00:20:57 UTC) multi-call binary
Usage: httpd [-ifv[v]] [-c CONFFILE] [-p [IP:]PORT] [-u USER[:GRP]] [-r REALM]
[-h HOME]
or httpd -d/-e/-m STRING
Listen for incoming HTTP requests
-i Inetd mode 插入模式
-f Don't daemonize 不要daemonize
#前台方式进行
-v[v] Verbose #显示访问日志
-p [IP:]PORT Bind to IP:PORT (default *:80) [IP:]PORT绑定IP:PORT(默认*:80)
-u USER[:GRP] Set uid/gid after binding to port USER[:GRP]绑定端口后设置uid/gid
-r REALM Authentication Realm for Basic Authentication REALM认证基本认证的域
-h HOME Home directory (default .)
#存放网页配置的文件目录
-c FILE Configuration file (default {/etc,HOME}/httpd.conf) 配置文件(default {/etc,HOME}/httpd.conf) #指定dockerfile 的相关语法
-m STRING MD5 crypt STRING STRING MD5密码加密字符串
-e STRING HTML encode STRING HTML编码
-d STRING URL decode STRING URL解码
/ # exit


#格式1
[root@ubuntu1804 ~]#docker commit -a "liangxiaoyu" -c 'CMD /bin/httpd -f -h /data/html' -c "EXPOSE 80" b1 httpd-busybox:v1.0
#格式2
[root@ubuntu1804 ~]#docker commit -a "liangxiaoyu" -c 'CMD ["/bin/httpd", "-f", "-v","-h", "/data/html"]' -c "EXPOSE 80" b1 httpdbusybox:v1.0

[root@ubuntu1804 ~]#docker images
REPOSITORY         TAG                 IMAGE ID           CREATED             docekr
SIZE
httpd-busybox       v1.0               e7883146c119        6 minutes ago      
1.22MB
[root@ubuntu1804 ~]#docker run -d -P --name httpd01 httpd-busybox:v1.0
ce95174c6385392b9699d12d1a86d7f81bc4dde1400a071ce17d9c78d905cb12
[root@ubuntu1804 ~]#docker port httpd01
80/tcp -> 0.0.0.0:32783dock
[root@ubuntu1804 ~]#docker inspect -f "
{{.NetworkSettings.Networks.bridge.IPAddress}}" httpd01
172.17.0.2

#对应格式1
[root@ubuntu1804 ~]#docker inspect -f "{{.Config.Cmd}}" httpd01
[/bin/sh -c /bin/httpd -f -h /data/html]

#对应格式2
[root@ubuntu1804 ~]#docker inspect -f "{{.Config.Cmd}}" httpd01
[/bin/httpd -f -h /data/html]
[root@ubuntu1804 ~]#docker exec -it httpd01 sh
/ # pstree -p
httpd(1)
/ # ps aux
PID   USER     TIME COMMAND
   1 root      0:00 /bin/httpd -fv -h /data/html
   7 root      0:00 sh
  13 root      0:00 ps aux
/ #
[root@ubuntu1804 ~]#curl 172.17.0.2
httpd website in busybox
[root@ubuntu1804 ~]#curl 127.0.0.1:32783
httpd website in busybox

#再次制作镜像v2.0版
[root@ubuntu1804 ~]#docker commit -a "wang<root@wangxiaochun.com>" b1 httpdbusybox:v2.0
[root@ubuntu1804 ~]#docker run -d --name web2 -p 81:80 httpd-busybox:v2.0 /bin/httpd -fv -h /data/html
c47bce0de75dcdf88266467accbe0a119190999c23cec32d6af8b8500aed96d4

#不能拿本机做验证哈

1.2.3 实战案例:基于官方镜像生成的容器制作tomcat 镜像

1.2.3.1 下载官方的tomcat 镜像并运行

[root@ubuntu1804 ~]#docker images
REPOSITORY         TAG                 IMAGE ID           CREATED            
SIZE

[root@ubuntu1804 ~]#docker run -d -p 8080:8080 tomcat
Unable to find image 'tomcat:latest' locally
latest: Pulling from library/tomcat
e9afc4f90ab0: Pull complete
989e6b19a265: Pull complete
af14b6c2f878: Pull complete
5573c4b30949: Pull complete
fb1a405f128d: Pull complete
612a9f566fdc: Pull complete
4226f9b63dac: Pull complete
cb8bfe875d7f: Pull complete
5aa366608b6d: Pull complete
4b7c9018ca5f: Pull complete
Digest: sha256:46456ccf216f2fde198844d5c7d511f60e3ffc2ea3828e0cce9a2eed566e48e2
Status: Downloaded newer image for tomcat:latest
6fcc5f7c1c7ce7be0b12007e310fc044e1077d489e1292b22621de55e302c455

[root@ubuntu1804 ~]#docker ps
CONTAINER ID       IMAGE               COMMAND             CREATED            
STATUS             PORTS                   NAMES
6fcc5f7c1c7c       tomcat              "catalina.sh run"   42 seconds ago    
Up 40 seconds       0.0.0.0:8080->8080/tcp   focused_wilbur

[root@ubuntu1804 ~]#curl -I 127.0.0.1:8080
HTTP/1.1 404
Content-Type: text/html;charset=utf-8
Content-Language: en
Transfer-Encoding: chunked
Date: Mon, 20 Jul 2020 15:33:21 GMT

1.2.3.1 修改容器

[root@ubuntu1804 ~]#docker exec -it 6fcc5f7c1c7c bash
root@6fcc5f7c1c7c:/usr/local/tomcat# ls
BUILDING.txt LICENSE README.md RUNNING.txt conf logs   temp    
webapps.dist
CONTRIBUTING.md NOTICE   RELEASE-NOTES bin     lib   native-jni-lib
webapps work

root@6fcc5f7c1c7c:/usr/local/tomcat# ls webapps 一般页面是不存在的 需要我们创建

root@6fcc5f7c1c7c:/usr/local/tomcat# ls webapps.dist/ 但是官方给我们准备了 我们需要改名字 或者复制就行了
ROOT docs examples host-manager manager

root@6fcc5f7c1c7c:/usr/local/tomcat# cp -a webapps.dist/* webapps/
#-a 保留属性

root@6fcc5f7c1c7c:/usr/local/tomcat# ls webapps/
ROOT docs examples host-manager manager

root@6fcc5f7c1c7c:/usr/local/tomcat# exit
exit

[root@ubuntu1804 ~]#curl -I 127.0.0.1:8080  
-I #只显示文档信息
HTTP/1.1 200
Content-Type: text/html;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 20 Jul 2020 15:34:24 GMT

1.2.3.2 提交镜像

[root@ubuntu1804 ~]#docker commit -m "add webapps app" -a "wangxiaochun" 6fcc5f7c1c7c tomcat:10.0.13-v1
sha256:b8d669ebf99e65d5ed69378d0d53f054e7de4865d335ab7aa0a7a5508e1369f7
[root@ubuntu1804 ~]#docker images
REPOSITORY         TAG                 IMAGE ID           CREATED            
SIZE
tomcat              9.0.37-v1           b8d669ebf99e        4 seconds ago      
652MB
tomcat             latest             df72227b40e1        3 days ago        
647MB
[root@ubuntu1804 ~]#docker history tomcat:9.0.37-v1
IMAGE               CREATED             CREATED BY                              
      SIZE               COMMENT
b8d669ebf99e        14 minutes ago     catalina.sh run                        
        4.84MB             add webapps app
df72227b40e1        3 days ago         /bin/sh -c #(nop) CMD ["catalina.sh"
"run"]   0B                  
<missing>           3 days ago         /bin/sh -c #(nop) EXPOSE 8080          
      0B                  
<missing>           3 days ago         /bin/sh -c set -e &&
nativeLines="$(catalin…   0B                  
<missing>           3 days ago         /bin/sh -c set -eux;  
savedAptMark="$(apt-m…   20MB                
<missing>           3 days ago         /bin/sh -c #(nop) ENV
TOMCAT_SHA512=077c3e6…   0B                  
<missing>           3 days ago         /bin/sh -c #(nop) ENV
TOMCAT_VERSION=9.0.37   0B                  
<missing>           3 days ago         /bin/sh -c #(nop) ENV TOMCAT_MAJOR=9  
        0B                  
<missing>           3 days ago         /bin/sh -c #(nop) ENV
GPG_KEYS=05AB33110949…   0B                  
<missing>           3 days ago         /bin/sh -c #(nop) ENV
LD_LIBRARY_PATH=/usr/…   0B                  
<missing>           3 days ago         /bin/sh -c #(nop) ENV
TOMCAT_NATIVE_LIBDIR=…   0B                  
<missing>           3 days ago         /bin/sh -c #(nop) WORKDIR
/usr/local/tomcat     0B                  
<missing>           3 days ago         /bin/sh -c mkdir -p "$CATALINA_HOME"    
      0B                  
<missing>           3 days ago         /bin/sh -c #(nop) ENV
PATH=/usr/local/tomca…   0B                  
<missing>           3 days ago         /bin/sh -c #(nop) ENV
CATALINA_HOME=/usr/lo…   0B                  
<missing>           3 days ago         /bin/sh -c #(nop) CMD ["jshell"]      
        0B                  
<missing>           3 days ago         /bin/sh -c set -eux;   dpkgArch="$(dpkg
--pr…   323MB              
<missing>           3 days ago         /bin/sh -c #(nop) ENV
JAVA_URL_VERSION=11.0…   0B                  
<missing>           3 days ago         /bin/sh -c #(nop) ENV
JAVA_BASE_URL=https:/…   0B                  
<missing>           3 days ago         /bin/sh -c #(nop) ENV
JAVA_VERSION=11.0.8     0B                  
<missing>           5 weeks ago         /bin/sh -c { echo '#/bin/sh'; echo 'echo
"$J…   27B                
<missing>           5 weeks ago         /bin/sh -c #(nop) ENV
PATH=/usr/local/openj…   0B                  
<missing>           5 weeks ago         /bin/sh -c #(nop) ENV
JAVA_HOME=/usr/local/…   0B                  
<missing>           5 weeks ago         /bin/sh -c #(nop) ENV LANG=C.UTF-8    
        0B                  
<missing>           5 weeks ago         /bin/sh -c set -eux; apt-get update;
apt-g…   11.1MB  
<missing>           5 weeks ago         /bin/sh -c apt-get update && apt-get
install…   146MB              
<missing>           5 weeks ago         /bin/sh -c set -ex;  if ! command -v gpg
> /…   17.5MB              
<missing>           5 weeks ago         /bin/sh -c apt-get update && apt-get
install…   16.5MB              
<missing>           5 weeks ago         /bin/sh -c #(nop) CMD ["bash"]        
        0B                  
<missing>           5 weeks ago         /bin/sh -c #(nop) ADD
file:1ab357efe422cfed5…   114MB
[root@ubuntu1804 ~]#docker inspect tomcat:9.0.37-v1 |tail -n20
           "Type": "layers",
           "Layers": [
             
"sha256:8803ef42039dcbe936755e9baae4bb7b19cb0fb6a438eb3992950cd0afef8e4f",
             
"sha256:c2c789d2d3c5fc15428921b5316a63907d8c312c5508cbac9a704bd30bcc740d",
             
"sha256:527ade4639e08d1b2ba9d0d46f3b43433310a2e8674ae808aeef5502b099ff3c",
             
"sha256:2e5b4ca91984c19a75bad687aedebf02609511a033aa0d3d15ac915593279718",
             
"sha256:f5181c7ef9028578eb0040a0051ce940c3f9ba62a51d3eb02ad52c3724db3e9b",
             
"sha256:f73b2345c404b2a65abc66ab68af6b112aafb9d2583416d2eb84a47139e4626e",
             
"sha256:afa12e842ed4e07340351e64318d3149b3ec8430f631d9bbe8e0d3ac24046cff",
             
"sha256:31d7eb4c72a987dd8742add724562e0e800998cb7a57f7ed0c6dffa0587b5af4",
             
"sha256:4b1785e8102bdcc4f7bb759d084e1f03b2b26c19fa42aa91c879ce26f36381d7",
             
"sha256:aca03caac7b1c380545a00f970a42079bbc8928c9785492e9e289f60206b01e1",
             
"sha256:860b0f130267d185ed8328a5fcd3ecd040a7afec64b63f7551c5f3af80709db5"
          ]
      },
       "Metadata": {
           "LastTagTime": "2020-07-20T23:42:00.403415564+08:00"
      }
  }
]
#删除当前的容器
[root@ubuntu1804 ~]#docker rm -f 6fcc5f7c1c7c
6fcc5f7c1c7c
[root@ubuntu1804 ~]#docker ps
CONTAINER ID       IMAGE               COMMAND             CREATED            
STATUS             PORTS               NAMES

1.2.3.4 利用新镜像启动容器

[root@ubuntu1804 ~]#docker run -d -p 8080:8080 --name tomcat tomcat:10.0.13-v1
97688b4c835da4b222f3ca15af36b8c27d4e60ff33480c314daf3f123b1cb50c
[root@ubuntu1804 ~]#docker ps
CONTAINER ID       IMAGE               COMMAND             CREATED            
STATUS             PORTS                   NAMES
97688b4c835d       tomcat:9.0.37-v1    "catalina.sh run"   6 seconds ago      
Up 5 seconds        0.0.0.0:8080->8080/tcp   tomcat

2.2.4 实战案例: 基于Ubuntu的基础镜像利用 apt 安装手动制作nginx 的镜像

1.2.4.1 启动Ubuntu基础镜像并实现相关的配置

#先拉取一个镜像
[root@ubuntu1804 ~]#docker pull ubuntu

[root@ubuntu1804 ~]#docker run -it -p 80 --name nginx_ubuntu ubuntu bash
# -p 80 容器80端口映射为本地端口

root@705148273eac:/# cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacypolicy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

root@705148273eac:/# ll /etc/apt/sources.list
-rw-r--r-- 1 root root 2743 Jul  3 02:00 /etc/apt/sources.list

#备份源文件
root@705148273eac:/#cp /etc/apt/sources.list /etc/apt/sources.bak

#更改为阿里云的镜像源
#方法一
root@705148273eac:/# cat > /etc/apt/sources.list
deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe
multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe
multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted
universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe
multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe
multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe
multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted
universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe
multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted
universe multiverse
^C
#方法二
root@705148273eac:/# sed -ri.bak 's#\/\/.*.ubuntu.com#//mirrors.aliyun.com#' /etc/apt/sources.list

root@705148273eac:/# apt update
Get:1 http://mirrors.aliyun.com/ubuntu focal InRelease [265 kB]
Get:2 http://mirrors.aliyun.com/ubuntu focal-security InRelease [107 kB]
Get:3 http://mirrors.aliyun.com/ubuntu focal-updates InRelease [111 kB]
Get:4 http://mirrors.aliyun.com/ubuntu focal-proposed InRelease [265 kB]
Get:5 http://mirrors.aliyun.com/ubuntu focal-backports InRelease [98.3 kB]
Get:6 http://mirrors.aliyun.com/ubuntu focal/restricted Sources [7198 B]
Get:7 http://mirrors.aliyun.com/ubuntu focal/multiverse Sources [208 kB]
......                          
Fetched 28.7 MB in 6s (4651 kB/s)                                              
                               
Reading package lists... Done
Building dependency tree      
Reading state information... Done
8 packages can be upgraded. Run 'apt list --upgradable' to see them.
root@705148273eac:/# apt -y install nginx
Reading package lists... Done
Building dependency tree      
Reading state information... Done
The following additional packages will be installed:
........
Configuring tzdata
------------------
Please select the geographic area in which you live. Subsequent configuration
questions will narrow this down
by presenting a list of cities, representing the time zones in which they are
located.
 1. Africa   3. Antarctica  5. Arctic  7. Atlantic  9. Indian    11. SystemV
13. Etc
 2. America  4. Australia   6. Asia    8. Europe    10. Pacific  12. US
Geographic area: 6 #指定时区
Please select the city or region corresponding to your time zone.
 1. Aden      16. Brunei       31. Hong_Kong    46. Kuala_Lumpur  61. Pyongyang
     76. Tehran
 2. Almaty    17. Chita        32. Hovd         47. Kuching       62. Qatar    
     77. Tel_Aviv
 3. Amman     18. Choibalsan   33. Irkutsk      48. Kuwait        63. Qostanay
      78. Thimphu
 4. Anadyr    19. Chongqing    34. Istanbul     49. Macau         64. Qyzylorda
     79. Tokyo
 5. Aqtau     20. Colombo      35. Jakarta      50. Magadan       65. Rangoon  
     80. Tomsk
 6. Aqtobe    21. Damascus     36. Jayapura     51. Makassar      66. Riyadh  
      81. Ujung_Pandang
 7. Ashgabat  22. Dhaka        37. Jerusalem    52. Manila        67. Sakhalin
      82. Ulaanbaatar
 8. Atyrau    23. Dili         38. Kabul        53. Muscat        68. Samarkand
     83. Urumqi
 9. Baghdad   24. Dubai        39. Kamchatka    54. Nicosia       69. Seoul    
     84. Ust-Nera
 10. Bahrain  25. Dushanbe     40. Karachi      55. Novokuznetsk  70. Shanghai
      85. Vientiane
 11. Baku     26. Famagusta    41. Kashgar      56. Novosibirsk   71. Singapore
     86. Vladivostok
 12. Bangkok  27. Gaza         42. Kathmandu    57. Omsk          72.
Srednekolymsk  87. Yakutsk
 13. Barnaul  28. Harbin       43. Khandyga     58. Oral          73. Taipei  
      88. Yangon
 14. Beirut   29. Hebron       44. Kolkata      59. Phnom_Penh    74. Tashkent
      89. Yekaterinburg
 15. Bishkek  30. Ho_Chi_Minh  45. Krasnoyarsk  60. Pontianak     75. Tbilisi  
     90. Yerevan
Time zone: 70   #配置时区
......
Setting up nginx-core (1.18.0-0ubuntu1) ...
invoke-rc.d: could not determine current runlevel
invoke-rc.d: policy-rc.d denied execution of start.
Setting up nginx (1.18.0-0ubuntu1) ...
Processing triggers for libc-bin (2.31-0ubuntu9) ...
root@705148273eac:/# nginx -v
nginx version: nginx/1.18.0 (Ubuntu)
root@705148273eac:~# grep include /etc/nginx/nginx.conf
include /etc/nginx/modules-enabled/*.conf;
include /etc/nginx/mime.types;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
root@705148273eac:~# grep root /etc/nginx/sites-enabled/default  
root /var/www/html;
# deny access to .htaccess files, if Apache's document root
# root /var/www/example.com;

root@705148273eac:/# echo Nginx Website in Docker > /var/www/html/index.html
root@705148273eac:/# exit
exit

1.2.4.2 提交镜像

[root@ubuntu1804 ~]#docker commit -a 'liangxiaoyu' -m 'nginx-ubuntu:20.04' nginx_ubuntu nginx_ubuntu20.04:v1.18.0
sha256:2c789ec21d2545c9bfc4af6d4380878153d52fcc03890aac755d09112631742a
[root@ubuntu1804 ~]#docker images  
REPOSITORY             TAG                 IMAGE ID           CREATED          
  SIZE
nginx_ubuntu20.04     v1.18.0             2c789ec21d25        22 seconds ago  
  179MB

1.2.4.3 从制作的新镜像启动容器并测试访问

[root@ubuntu1804 ~]#docker run -d -p 80 --name nginx-web nginx_ubuntu20.04:v1.18.0 nginx -g 'daemon off;'
#详情见下面解释
b0c8496a497ba60f7b5bc430b075b00d40c7ace24068e71decac625e84df40de
[root@ubuntu1804 ~]#docker ps
CONTAINER ID       IMAGE                       COMMAND                 CREATED
            STATUS             PORTS                   NAMES
b0c8496a497b       nginx_ubuntu20.04:v1.18.0   "nginx -g 'daemon of…"   7
seconds ago       Up 5 seconds        0.0.0.0:32771->80/tcp   nginx-web
[root@ubuntu1804 ~]#docker port nginx-web
80/tcp -> 0.0.0.0:32771
[root@ubuntu1804 ~]#curl http://127.0.0.1:32771
Nginx Website in Docker

解释

问题:1.docker容器跑着为啥会挂掉?

docker 容器默认会把容器内部第一个进程,也就是pid=1的程序作为docker容器是否正在运行的依据,如果docker 容器pid挂了,那么docker容器便会直接退出。

问题2.docker run的时候把command最为容器内部命令,如果你使用nginx,那么nginx程序将后台运行,这个时候nginx并不是pid为1的程序,而是执行的bash,这个bash执行了nginx指令后就挂了,所以容器也就退出了,和你这个一样的道理,pm2 start 过后,bash 的pid为1,那么此时bash执行完以后会退出,所以容器也就退出了。

官方nignx的docker 仓库原文说明如下

 

If you add a custom CMD in the Dockerfile, be sure to include -g daemon off; in the CMD in order for nginx to stay in the foreground, so that Docker can track the process properly (otherwise your container will stop immediately after starting)!


Running nginx in debug mode
Images since version 1.9.8 come with nginx-debug binary that produces verbose output when using higher log levels. It can be used with simple CMD substitution:

$ docker run --name my-nginx -v /host/path/nginx.conf:/etc/nginx/nginx.conf:ro -d nginx nginx-debug -g 'daemon off;'
Similar configuration in docker-compose.yml may look like this:

web:
image: nginx
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
command: [nginx-debug, '-g', 'daemon off;']

1.2.5 实战案例: 基于CentOS的基础镜像利用 yum 安装手动制作nginx 的镜像

1.2.5.1下载基础镜像并初始化系统

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

[root@ubuntu1804 ~]#docker pull centos
[root@ubuntu1804 ~]#docker images
REPOSITORY         TAG                 IMAGE ID           CREATED            
SIZE
centos             centos7.7.1908     08d05d1d5859        2 months ago      
204MB
[root@ubuntu1804 ~]#docker run -it --name cenots8 centos bash
#修改时区
[root@9caa8742e6ce /]#rm -f /etc/localtime
[root@9caa8742e6ce /]#ln -s ../usr/share/zoneinfo/Asia/Shanghai /etc/localtime

#更改yum 源
[root@9caa8742e6ce /]# yum -y install wget
[root@9caa8742e6ce /]# mkdir /etc/yum.repos.d/base.bak
[root@9caa8742e6ce /]# mv /etc/yum.repos.d/C* /etc/yum.repos.d/base.bak
[root@9caa8742e6ce /]# rm -rf /etc/yum.repos.d/*
[root@9caa8742e6ce /]# wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-8.repo

#或者可以从宿主机从拷贝过去
[root@centos8 ~]#scp /etc/yum.repo.d/base.repo 10.0.0.10:/
[root@centos8 ~]# docker cp -a base.repo centos1:/etc/yum.repos.d/

#安装epel
[root@9caa8742e6ce /]# yum install -y https://mirrors.aliyun.com/epel/epel-release-latest-8.noarch.rpm
[root@9caa8742e6ce /]#sed -i 's|^#baseurl=https://download.example/pub|baseurl=https://mirrors.aliyun.com|' /etc/yum.repos.d/epel*
sed -i 's|^metalink|#metalink|' /etc/yum.repos.d/epel*

1.2.5.2 安装相关软件和工具

#yum安装nginx
[root@9caa8742e6ce /]# yum -y install nginx

#安装常用命令
[root@9caa8742e6ce /]# yum install -y vim curl iproute net-tools

#为了减少镜像大小 清理yum缓存
[root@9caa8742e6ce /]# rm -rf /var/cache/yum/*

1.2.5.3 修改服务的配置信息关闭服务后台运行

#关闭nginx后台运行
[root@9caa8742e6ce /]# vim /etc/nginx/nginx.conf
user nginx; #选项下班添加一下内容
daemon off; #关闭后台运行

#或者按照上面方法安装

image-20211203143958206

1.2.5.4 准备程序和数据

#自定义web界面
[root@9caa8742e6ce ~]# rm -f /usr/share/nginx/html/index.html
[root@9caa8742e6ce ~]# echo "Nginx Page in Docker" >/usr/share/nginx/html/index.html

1.2.5.5 提交为镜像

docker commit 命令在宿主机基于容器ID 提交为镜像

#不关闭容器的情况,将容器提交为镜像
[root@ubuntu1804 ~]#docker commit -a "root@wangxiaochun.com" -m "nginx yum v1" -c "EXPOSE 80 443" centos8 lxy/centos7-nginx:1.16.1.v1
#-c "EXPOSE 80 443" 使用dockerfeile 创建镜像,然后暴露 80 和 443 端口
sha256:e9d09cc585ed8ee1544b1e68de326ea6dcbe99577fc9b2edad9ab481b7a7e7ec
[root@ubuntu1804 ~]#docker images
REPOSITORY           TAG                 IMAGE ID           CREATED            
SIZE
wang/centos7-nginx   1.16.1.v1           e9d09cc585ed        4 seconds ago      
442MB
centos               centos7.7.1908     08d05d1d5859        2 months ago      
204MB

1.2.5.6 从制作的镜像启动容器

[root@ubuntu1804 ~]#docker run -d -p 8080:80 --name my-centos-nginx lxy/centos7-nginx:1.16.1.v1 /usr/sbin/nginx 
c60f8373a14210bb3aa06ce03c2258a4b912033b0650ef690f9245fc3afc5bf1
[root@ubuntu1804 ~]#docker ps
CONTAINER ID       IMAGE                         COMMAND             CREATED  
          STATUS             PORTS                           NAMES
c60f8373a142       wang/centos7-nginx:1.16.1.v1   "/usr/sbin/nginx"   6 seconds
ago       Up 5 seconds        443/tcp, 0.0.0.0:8080->80/tcp   my-centos-nginx
9caa8742e6ce       centos:centos7.7.1908          "bash"              35
minutes ago     Up 35 minutes                                      
thirsty_hypatia
[root@ubuntu1804 ~]#

1.2.5.7 访问测试镜像

[root@ubuntu1804 ~]#curl 127.0.0.1:8080
Nginx Page in Docker
[root@ubuntu1804 ~]#

1.2.6 实战案例: 基于CentOS 基础镜像手动制作编译版本 nginx 镜像

在CentOS 基础镜像的容器之上手动编译安装nginx,然后再将此容器提交为镜像

1.2.6.1 下载镜像并初始化系统

[root@ubuntu1804 ~]#docker pull centos
[root@ubuntu1804 ~]#docker images
REPOSITORY         TAG                 IMAGE ID           CREATED            
SIZE
centos             centos7.7.1908     08d05d1d5859        2 months ago      
204MB
[root@ubuntu1804 ~]#docker run -it centos /bin/bash
#修改时区
[root@9caa8742e6ce /]#rm -f /etc/localtime
[root@9caa8742e6ce /]#ln -s ../usr/share/zoneinfo/Asia/Shanghai /etc/localtime
#生成yum源配置
#更改yum 源
[root@9caa8742e6ce /]# yum -y install wget
[root@9caa8742e6ce /]# mkdir /etc/yum.repos.d/base.bak
[root@9caa8742e6ce /]# mv /etc/yum.repos.d/C* /etc/yum.repos.d/base.bak
[root@9caa8742e6ce /]# rm -rf /etc/yum.repos.d/*
[root@9caa8742e6ce /]# wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-8.repo

#或者可以从宿主机从拷贝过去
[root@centos8 ~]#scp /etc/yum.repo.d/base.repo 10.0.0.10:/
[root@centos8 ~]# docker cp -a base.repo centos1:/etc/yum.repos.d/

#安装epel
[root@9caa8742e6ce /]# yum install -y https://mirrors.aliyun.com/epel/epel-release-latest-8.noarch.rpm
[root@9caa8742e6ce /]#sed -i 's|^#baseurl=https://download.example/pub|baseurl=https://mirrors.aliyun.com|' /etc/yum.repos.d/epel*
sed -i 's|^metalink|#metalink|' /etc/yum.repos.d/epel*

 

1.2.6.2 编译安装 nginx

[root@64944257fa88 /]# useradd -r -s /sbin/nologin nginx
#安装基础包
[root@64944257fa88 /]# yum -y install gcc gcc-c++ automake pcre pcre-devel zlib zlib-devel openssl openssl-devel
[root@64944257fa88 /]# cd /usr/local/src
[root@64944257fa88 src]# wget http://nginx.org/download/nginx-1.16.1.tar.gz
[root@64944257fa88 src]# tar xf nginx-1.16.1.tar.gz
[root@64944257fa88 src]# cd nginx-1.16.1
[root@64944257fa88 nginx-1.16.1]# ./configure --prefix=/apps/nginx
[root@64944257fa88 nginx-1.16.1]# yum -y install make
[root@64944257fa88 nginx-1.16.1]# make && make install
[root@64944257fa88 nginx-1.16.1]# rm -rf nginx*
[root@64944257fa88 nginx-1.16.1]# rm -rf /var/cache/yum/*

1.2.6.3 关闭 nginx 后台运行

[root@64944257fa88 nginx-1.16.1]# cd /apps/nginx/    
[root@64944257fa88 nginx]# ls
conf html logs sbin
[root@64944257fa88 nginx]# vi conf/nginx.conf
user nginx;#添加下面命令
daemon off;#关闭后台执行
[root@64944257fa88 nginx]# ln -s /apps/nginx/sbin/nginx /usr/sbin/
[root@64944257fa88 nginx]# ll /usr/sbin/nginx
lrwxrwxrwx 1 root root 22 Jan 28 05:29 /usr/sbin/nginx -> /apps/nginx/sbin/nginx

1.2.6.4 准备相关数据自定义web界面

[root@64944257fa88 nginx]# echo "Nginx Test Page in Docker" > 
/apps/nginx/html/index.html

1.2.6.5 提交为镜像

#不要退出容器,在另一个终端窗口执行以下命令
[root@ubuntu1804 ~]#docker images
REPOSITORY         TAG                 IMAGE ID           CREATED            
SIZE
centos             centos7.7.1908     08d05d1d5859        2 months ago      
204MB
[root@ubuntu1804 ~]#docker ps
CONTAINER ID       IMAGE                   COMMAND             CREATED        
    STATUS             PORTS               NAMES
64944257fa88       centos:centos7.7.1908   "/bin/bash"         18 seconds ago  
  Up 17 seconds                           stupefied_albattani
[root@ubuntu1804 ~]#docker commit -m "nginx1.6.1" 64944257fa88 -c "CMD nginx"
centos7-nginx:1.6.1
sha256:d86d957bb00f35fe09ae38230e1e2d12916f4406e997146c68e34dae7526c079
[root@ubuntu1804 ~]#docker images
REPOSITORY         TAG                 IMAGE ID           CREATED            
SIZE
centos7-nginx       1.6.1               d86d957bb00f        2 minutes ago      
486MB
centos             centos7.7.1908     08d05d1d5859        2 months ago      
204MB

1.2.6.6 从自己的镜像启动容器

[root@ubuntu1804 ~]#docker run -d -p 80:80 centos7-nginx:1.6.1 nginx
ae90b1abf374138a21f7ed104d14c88f1af23c0b2027c3fe099722fd7fbad3a4
[root@ubuntu1804 ~]#docker ps
CONTAINER ID       IMAGE                 COMMAND             CREATED          
  STATUS             PORTS               NAMES
ae90b1abf374       centos7-nginx:1.6.1   "nginx"             About a minute ago
  Up About a minute   0.0.0.0:80->80/tcp   naughty_thompson

备注: 最后面的nginx是运行的命令,即镜像里面要运行一个nginx命令,所以前面软链接到/usr/sbin/nginx,目的为了让系统不需要指定路径就可以执行此命令

1.2.6.7 访问测试

[root@ubuntu1804 ~]#curl 127.0.0.1
Nginx Test Page in Docker

1.2.6.8 查看Nginx访问日志和进程

[root@ubuntu1804 ~]#docker exec -it ae90b1abf374 bash
[root@ae90b1abf374 /]# cat /apps/nginx/logs/access.log
172.17.0.1 - - [28/Jan/2020:05:40:51 +0000] "GET / HTTP/1.1" 200 26 "-"
"curl/7.58.0"
[root@ae90b1abf374 /]# ps aux
USER       PID %CPU %MEM   VSZ   RSS TTY     STAT START   TIME COMMAND
root          1  0.0  0.2  20572  2468 ?       Ss   05:40   0:00 nginx: master
process nginx
nginx         6  0.0  0.3  21024  3104 ?       S    05:40   0:00 nginx: worker
process
root          7  0.3  0.2  11840  2928 pts/0   Ss   05:45   0:00 bash
root         21  0.0  0.3  51764  3344 pts/0   R+   05:46   0:00 ps aux

1.3 利用 DockerFile 文件执行 docker build 自动构建镜

1.3.1 Dockfile 使用详解

1.3.1.1 Dockerfile 介绍

DockerFile 是一种被Docker程序解释执行的脚本,由一条条的命令组成的,每条命令对应linux下面的一条命令,Docker程序将这些DockerFile指令再翻译成真正的linux命令,其有自己的书写方式和支持的命令,Docker程序读取DockerFile并根据指令生成Docker镜像,相比手动制作镜像的方式,DockerFile更能直观的展示镜像是怎么产生的,有了DockerFile,当后期有额外的需求时,只要在之前的DockerFile添加或者修改响应的命令即可重新生成新的Docker镜像,避免了重复手动制作镜像的麻烦,类似与shell脚本一样,可以方便高效的制作镜像Docker守护程序 Dockerfile 逐一运行指令,如有必要,将每个指令的结果提交到新镜像,然后最终输出新镜像的ID。Docker守护程序将自动清理之前发送的上下文请注意,每条指令都是独立运行的,并会导致创建新镜像,比如 RUN cd /tmp 对下一条指令不会有任何影响。

Docker将尽可能重用中间镜像层(缓存),以显著加速 docker build 命令的执行过程,这由 Using cache 控制台输出中的消息指示

1.3.1.2 Dockerfile 镜像制作和使用流程

image-20211204091933537

1.3.1.3 Dockerfile文件的制作镜像的分层结构

image-20211204092001462

范例:

#按照业务类型或系统类型等方式划分创建目录环境,方便后期镜像比较多的时候进行分类
[root@ubuntu1804 ~]#mkdir
/data/dockerfile/{web/{nginx,apache,tomcat,jdk},system/{centos,ubuntu,alpine,deb
ian}} -p
[root@ubuntu1804 ~]#tree /data/dockerfile/
/data/dockerfile/
├── system
│   ├── alpine
│   ├── centos
│   ├── debian
│   └── ubuntu
└── web
  ├── apache
  ├── jdk
  ├── nginx
  └── tomcat
10 directories, 0 files
[root@ubuntu1804 ~]#

1.3.1.4 Dockerfile 文件格式

Dockerfile 是一个有特定语法格式的文本文件 dockerfile 官方说明: https://docs.docker.com/engine/reference/builder/ 帮助: man 5 dockerfile

Dockerfile 文件说明

  • 每一行以Dockerfile的指令开头,指令不区分大小写,但是惯例使用大写

  • 使用 # 开始作为注释

  • 每一行只支持一条指令,每条指令可以携带多个参数

  • 指令按文件的顺序从上至下进行执行

  • 每个指令的执行会生成一个新的镜像层,为了减少分层和镜像大小,尽可能将多条指令合并成一条指令

  • 制作镜像一般可能需要反复多次,每次执行dockfile都按顺序执行,从头开始,已经执行过的指令已经缓存,不需要再执行,如果后续有一行新的指令没执行过,其往后的指令将会重新执行,所以为加速镜像制作,将最常变化的内容放下dockerfile的文件的后面

1.3.1.5 Dockerfile 相关指令

dockerfile 文件中的常见指令:

ADD
COPY
ENV
EXPOSE
FROM
LABEL
STOPSIGNAL
USER
VOLUME
WORKDIR
1.3.1.5.1 FROM: 指定基础镜像

定制镜像,需要先有一个基础镜像,在这个基础镜像上进行定制。

FROM 就是指定基础镜像,此指令通常必需放在Dockerfile文件第一个非注释行。后续的指令都是运行于此基准镜像所提供的运行环境

基础镜像可以是任何可用镜像文件,默认情况下,docker build会在docker主机上查找指定的镜像文件,在其不存在时,则会从Docker Hub Registry上拉取所需的镜像文件.如果找不到指定的镜像文件,docker build会返回一个错误信息

如何选择合适的镜像呢?

对于不同的软件官方都提供了相关的docker镜像,比如: nginx、redis、mysql、httpd、tomcat等服 务类的镜像,也有操作系统类,如: centos、ubuntu、debian等。建议使用官方镜像,比较安全。

格式: ‘;

FROM [--platform=<platform>] <image> [AS <name>]
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
#说明:  
--platform 指定镜像的平台,比如: linux/amd64, linux/arm64, or windows/amd64
tag 和 digest是可选项,如果不指定,默认为latest

说明: 关于scratch 镜像

FROM scratch
参考链接:
https://hub.docker.com/_/scratch?tab=description
https://docs.docker.com/develop/develop-images/baseimages/
该镜像是一个空的镜像,可以用于构建busybox等超小镜像,可以说是真正的从零开始构建属于自己的镜像
该镜像在构建基础镜像(例如debian和busybox)或超最小镜像(仅包含一个二进制文件及其所需内容,例
如:hello-world)的上下文中最有用。

范例:

FROM scratch #所有镜像的起源镜像,相当于Object类
FROM ubuntu
FROM ubuntu:bionic
FROM debian:buster-slim
1.3.1.5.2 LABEL: 指定镜像元数据

可以指定镜像元数据,如: 镜像作者等

LABEL <key>=<value> <key>=<value> <key>=<value> ...

范例:

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."

一个镜像可以有多个label ,还可以写在一行中,即多标签写法,可以减少镜像的的大小

范例: 多标签写法

#一行格式
LABEL multi.label1="value1" multi.label2="value2" other="value3"
#多行格式
LABEL multi.label1="value1" \
    multi.label2="value2" \
     other="value3"

docker inspect 命令可以查看LABEL

范例:

"Labels": {
   "com.example.vendor": "ACME Incorporated"
   "com.example.label-with-value": "foo",
   "version": "1.0",
   "description": "This text illustrates that label-values can span multiple
lines.",
   "multi.label1": "value1",
   "multi.label2": "value2",
   "other": "value3"
},

MAINTAINER: 指定维护者信息

此指令已过时,,用LABEL代替

MAINTAINER <name>

范例:

MAINTAINER wangxiaochun <root@wangxiaochun.com>
#用LABEL代替
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
1.3.1.5.3 RUN: 执行 shell命令

RUN 指令用来在构建镜像阶段需要执行 FROM 指定镜像所支持的Shell命令。

通常各种基础镜像一般都支持丰富的shell命令

注意: RUN 可以写多个,每一个RUN指令都会建立一个镜像层,所以尽可能合并成一条指令,比如将多个shell命令通过 && 连接一起成为在一条指令

每个RUN都是独立运行的,和前一个RUN无关

#shell 格式: 相当于 /bin/sh -c <命令> 此种形式支持环境变量
RUN <命令>
#exec 格式: 此种形式不支持环境变量,注意:是双引号,不能是单引号
RUN ["可执行文件", "参数1", "参数2"]
#exec格式可以指定其它shell
RUN ["/bin/bash","-c","echo hello wang"]

说明:

shell格式中,<command>通常是一个shell命令,且以"/bin/sh -c”来运行它,这意味着此进程在容器中的PID不为1,不能接收Unix信号,因此,当使用docker stop <container>命令停止容器时,此进程接收不到SIGTERM信号

exec格式中的参数是一个JSON格式的数组,其中<executable>为要运行的命令,后面的<paramN>为传递给命令的选项或参数;然而,此种格式指定的命令不会以"/bin/sh -c"来发起,因此常见的shell操作如变量替换以及通配符(?,*等)替换将不会进行;不过,如果要运行的命令依赖于此shell特性的话,可以将其替换为类似下面的格式。

RUN ["/bin/bash", "-c", "<executable>", "<param1>"]

范例:

RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
RUN ["/bin/bash", "-c", "echo hello world"]
RUN yum -y install epel-release \
    && yum -y install nginx \
    && rm -rf /usr/share/nginx/html/*
    && echo "<h1> docker test nginx </h1>" > /usr/share/nginx/html/index.html

范例: 多个 前后RUN 命令独立无关和shell命令不同

#world.txt并不存放在/app内
RUN cd /app
RUN echo "hello" > world.txt
2.3.1.5.4 ENV: 设置环境变量

ENV 可以定义环境变量和值,会被后续指令(如:ENV,ADD,COPY,RUN等)通过$KEY或${KEY}进行引用,并在容器运行时保持

#变量赋值格式1
ENV <key> <value>   #此格式只能对一个key赋值,<key>之后的所有内容均会被视作其<value>的组成
部分
#变量赋值格式2
ENV <key1>=<value1> <key2>=<value2> \  #此格式可以支持多个key赋值,定义多个变量建议使用,
减少镜像层
<key3>=<value3> ...

#如果<value>中包含空格,可以以反斜线\进行转义,也可通过对<value>加引号进行标识;另外,反斜线也
可用于续行
#只使用一次变量
RUN <key>=<value> <command>
   
#引用变量
RUN $key .....
#变量支持高级赋值格式
${key:-word}
${kye:+word}

如果运行容器时如果需要修改变量,可以执行下面通过基于 exec 机制实现

注意: 下面方式只影响容器运行时环境,而不影响构建镜像的过程,即只能覆盖docker run时的环境变量,而不会影响docker build时环境变量的值

docker run -e|--env <key>=<value>
#说明
-e, --env list   #Set environment variables
   --env-file filename     #Read in a file of environment variables

示例: 两种格式功能相同

#格式1
ENV myName="John Doe" myDog=Rex\ The\ Dog \
   myCat=fluffy
#格式2
ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat fluffy

范例:

ENV VERSION=1.0 DEBUG=on NAME="Happy Feet"
ENV PG_MAJOR 9.3
ENV PG_VERSION 9.3.4
RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC
/usr/src/postgress && …
ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH

范例:

[root@ubuntu1804 dockerfile]#cat Dockerfile
FROM busybox
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
ENV NAME wang xiao chun
RUN touch $NAME.txt
[root@ubuntu1804 dockerfile]#cat build.sh
#!/bin/bash
#
TAG=$1
docker build -t test:$TAG .
[root@ubuntu1804 dockerfile]#./build.sh v5.0
[root@ubuntu1804 dockerfile]#docker run --rm --name c1 test:v5.0 env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=d4e1f89aca71
NAME=wang xiao chun
HOME=/root
[root@ubuntu1804 dockerfile]#docker run --rm -e NAME=mage --name c1 test:v5.0
env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=b23500aa100d
NAME=mage
HOME=/root
[root@ubuntu1804 dockerfile]#docker run --rm -e NAME=mage --name c1 test:v5.0
ls -l
total 36
drwxr-xr-x    2 root     root         12288 Jun 27 00:21 bin
-rw-r--r--    1 root     root             0 Jul 24 10:05 chun.txt
drwxr-xr-x    5 root     root           340 Jul 24 10:05 dev
drwxr-xr-x    1 root     root          4096 Jul 24 10:05 etc
drwxr-xr-x    2 nobody   nogroup       4096 Jun 27 00:21 home
dr-xr-xr-x  222 root     root             0 Jul 24 10:05 proc
drwx------    2 root     root          4096 Jun 27 00:21 root
dr-xr-xr-x   13 root     root             0 Jul 24 10:05 sys
drwxrwxrwt    2 root     root          4096 Jun 27 00:21 tmp
drwxr-xr-x    3 root     root          4096 Jun 27 00:21 usr
drwxr-xr-x    4 root     root          4096 Jun 27 00:21 var
-rw-r--r--    1 root     root             0 Jul 24 10:05 wang
-rw-r--r--    1 root     root             0 Jul 24 10:05 xiao
[root@ubuntu1804 dockerfile]#cat env.txt
NAME=wang
TITLE=cto
[root@ubuntu1804 dockerfile]#docker run --rm --env-file env.txt --name c1
test:v5.0 env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=88ddf5b73a6b
NAME=wang
TITLE=cto
HOME=/root
1.3.1.5.5 COPY: 复制文本

复制本地宿主机的 到容器中的 。

COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"] #路径中有空白字符时,建议使用此格式

说明:

可以是多个,可以使用通配符,通配符规则满足Go的filepath.Match 规则filepath.Match 参考链接: https://golang.org/pkg/path/filepath/#Match

必须是build上下文中的路径(为 Dockerfile 所在目录的相对路径),不能是其父目录中的文件

如果是目录,则其内部文件或子目录会被递归复制,但目录自身不会被复制

如果指定了多个, 或在中使用了通配符,则必须是一个目 录,且必须以 / 结尾

可以是绝对路径或者是 WORKDIR 指定的相对路径

使用 COPY 指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等

如果事先不存在,它将会被自动创建,这包括其父目录路径,即递归创建目录

范例:

COPY hom* /mydir/    
COPY hom?.txt /mydir/
1.3.1.5.6 ADD: 复制和解包文件

该命令可认为是增强版的COPY,不仅支持COPY,还支持自动解缩。可以将复制指定的 到容器中的

ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]

说明:

  • 可以是Dockerfile所在目录的一个相对路径;也可是一个 URL;还可是一个 tar 文件(自动解压)

  • 可以是绝对路径或者是 WORKDIR 指定的相对路径

  • 如果是目录,只复制目录中的内容,而非目录本身

  • 如果是一个 URL ,下载后的文件权限自动设置为 600

  • 如果为URL且不以/结尾,则指定的文件将被下载并直接被创建为,如果以 / 结尾,则文件名URL指定的文件将被直接下载并保存为/< filename>

  • 如果是一个本地文件系统上的打包文件,如: gz, bz2 ,xz ,它将被解包 ,其行为类似于"tar -x"命令,但是通过URL获取到的tar文件将不会自动展开

  • 如果有多个,或其间接或直接使用了通配符,则必须是一个以/结尾的目录路径;如果不以/结尾,则其被视作一个普通文件,的内容将被直接写入到

范例:

ADD test relativeDir/          # adds "test" to `WORKDIR`/relativeDir/
ADD test /absoluteDir/         # adds "test" to /absoluteDir/
ADD --chown=55:mygroup files* /somedir/
ADD --chown=bin files* /somedir/
ADD --chown=1 files* /somedir/
ADD --chown=10:11 files* /somedir/
ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz /
1.3.1.5.7 CMD: 容器启动命令

image-20211204102131117

一个容器中需要持续运行的进程一般只有一个,CMD 用来指定启动容器时默认执行的一个命令,且其运行结束后,容器也会停止,所以一般CMD 指定的命令为持续运行且为前台命令.

  • 如果docker run没有指定任何的执行命令或者dockerfile里面也没有ENTRYPOINT,那么开启容器时就会使用执行CMD指定的默认的命令

  • 前面介绍过的 RUN 命令是在构建镜像进执行的命令,注意二者的不同之处

  • 每个 Dockerfile 只能有一条 CMD 命令。如指定了多条,只有最后一条被执行

  • 如果用户启动容器时用 docker run xxx 指定运行的命令,则会覆盖 CMD 指定的命令

# 使用 exec 执行,推荐方式,第一个参数必须是命令的全路径,此种形式不支持环境变量
CMD ["executable","param1","param2"]
# 在 /bin/sh 中执行,提供给需要交互的应用;此种形式支持环境变量
CMD command param1 param2
# 提供给 ENTRYPOINT 命令的默认参数
CMD ["param1","param2"]

范例:

CMD ["nginx", "-g", "daemon off;"]

范例:

[root@ubuntu1804 dockerfile]#cat Dockerfile 
FROM ubuntu:18.04
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
RUN apt update \
&& apt -y install  curl \
&& rm -rf /var/lib/apt/lists/*
CMD [ "curl", "-s","https://ip.cn"]
[root@centos8 ubuntu]#podman run 9b
{"ip": "111.199.187.36", "country": "北京市", "city": "联通"}
#cat /etc/etc/issue覆盖了curl命令
[root@centos8 ubuntu]#podman run 9b cat /etc/issue
Ubuntu 18.04.4 LTS \n \l

范例:

[root@ubuntu1804 dockerfile]#pwd
/data/dockerfile
[root@ubuntu1804 dockerfile]#cat Dockerfile
FROM busybox
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
ENV ROOT /data/website
COPY index.html ${ROOT}/index.html
CMD /bin/httpd -f -h ${ROOT}
EXPOSE 80
[root@ubuntu1804 dockerfile]#cat index.html
Website in Dockerfile
[root@ubuntu1804 dockerfile]#cat build.sh
#!/bin/bash
#
TAG=$1
docker build -t test:$TAG .
[root@ubuntu1804 dockerfile]#./build.sh v1.0
[root@ubuntu1804 dockerfile]#docker run -d --rm -P --name c1 test:v1.0
[root@ubuntu1804 ~]#docker port c1
80/tcp -> 0.0.0.0:32781
[root@ubuntu1804 ~]#curl 127.0.0.1:32781
Website in Dockerfile
[root@ubuntu1804 ~]#

范例:

[root@ubuntu1804 dockerfile]#pwd
/data/dockerfile
[root@ubuntu1804 dockerfile]#cat Dockerfile
FROM busybox
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
ENV ROOT /data/website
RUN mkdir -p ${ROOT} && echo '<h1> Busybox httpd server in Dockerfile</h1>' >
${ROOT}/index.html
#COPY index.html ${ROOT}/index.html
CMD ["/bin/sh","-c","/bin/httpd -f -h ${ROOT}"]
#CMD /bin/httpd -f -h ${ROOT}
EXPOSE 80
[root@ubuntu1804 dockerfile]#cat build.sh
#!/bin/bash
#
TAG=$1
docker build -t test:$TAG .
[root@ubuntu1804 dockerfile]#ls
build.sh Dockerfile
[root@ubuntu1804 dockerfile]#./build.sh v2.0
Sending build context to Docker daemon  4.096kB
Step 1/5 : FROM busybox
---> c7c37e472d31
Step 2/5 : ENV ROOT /data/website
---> Using cache
---> ad654b3213c7
Step 3/5 : RUN mkdir -p ${ROOT} && echo '<h1> Busybox httpd server in
Dockerfile</h1>' > ${ROOT}/index.html
---> Running in c7c2b920ccb0
Removing intermediate container c7c2b920ccb0
---> d40ce17d4e85
Step 4/5 : CMD ["/bin/sh","-c","/bin/httpd -f -h ${ROOT}"]
---> Running in 52be24840eee
Removing intermediate container 52be24840eee
---> d22731d921df
Step 5/5 : EXPOSE 80
---> Running in 4a50d8d9aa83
Removing intermediate container 4a50d8d9aa83
---> 85d6547a3168
Successfully built 85d6547a3168
Successfully tagged test:v2.0
[root@ubuntu1804 dockerfile]#docker run -d --rm -P --name c2 test:v2.0
cf5fea09ce1362f18a90f4fcdffa3000de26b4919927e1cdce0cce6243f5dd24
[root@ubuntu1804 dockerfile]#docker port c2
80/tcp -> 0.0.0.0:32785
[root@ubuntu1804 dockerfile]#curl 127.0.0.1:32785
<h1> Busybox httpd server in Dockerfile</h1>
[root@ubuntu1804 dockerfile]#docker inspect -f "{{.Config}}" test:v2.0
{   false false false map[80/tcp:{}] false false false
[PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ROOT=/data/website] [/bin/sh -c /bin/httpd -f -h ${ROOT}] <nil> false
sha256:d22731d921df65f9da7452e714cf35ef345529ffa1bd5b92c0024d1d1bd8e714 map[]
[] false [] map[] <nil> []}
#查看进程关系
[root@ubuntu1804 ~]#docker exec -it c2 sh
/ # ps
PID   USER     TIME COMMAND
   1 root      0:00 /bin/httpd -f -h /data/website
   8 root      0:00 sh
  13 root      0:00 ps

1.3.1.5.8 ENTRYPOINT: 入口点

功能类似于CMD,配置容器启动后执行的命令及参数

# 使用 exec 执行
ENTRYPOINT ["executable", "param1", "param2"]
# shell中执行
ENTRYPOINT command param1 param2
  • ENTRYPOINT 不能被 docker run 提供的参数覆盖,而是追加,即如果docker run 命令有参数,那么参数全部都会作为ENTRYPOINT的参数

  • 如果docker run 后面没有额外参数,但是dockerfile中的CMD里有(即上面CMD的第三种用法),即Dockerfile中即有CMD也有ENTRYPOINT,那么CMD的全部内容会作为ENTRYPOINT的参数

  • 如果docker run 后面有额外参数,同时Dockerfile中即有CMD也有ENTRYPOINT,那么docker run后面的参数覆盖掉CMD参数内容,最终作为ENTRYPOINT的参数

  • 可以通过docker run --entrypoint string 参数在运行时替换,注意string不要加空格使用CMD要在运行时重新写命令本身,然后在后面才能追加运行参数,ENTRYPOINT则可以运行时无需重写命令就可以直接接受新参数

  • 每个 Dockerfile 中只能有一个 ENTRYPOINT,当指定多个时,只有最后一个生效

范例:

[root@ubuntu1804 ~]#docker run -it --entrypoint cat alpine /etc/issue
Welcome to Alpine Linux 3.12
Kernel \r on an \m (\l)

范例:

[root@ubuntu1804 dockerfile]#cat Dockerfile
FROM ubuntu:18.04
RUN apt update \
&& apt -y install  curl \
&& rm -rf /var/lib/apt/lists/*
ENTRYPOINT [ "curl", "-s","https://ip.cn"]
[root@centos8 dockerfile]#podman run -it --rm f68e006
{"ip": "111.199.187.36", "country": "北京市", "city": "联通"}
#追加-i参数
[root@centos8 dockerfile]#podman run -it --rm f68e006 -i
HTTP/2 200
date: Sun, 23 Feb 2020 08:05:19 GMT
content-type: application/json; charset=UTF-8
set-cookie: __cfduid=d4a22496ea6f3b2861763354f8ca600711582445119; expires=Tue,
24-Mar-20 08:05:19 GMT; path=/; domain=.ip.cn; HttpOnly; SameSite=Lax
cf-cache-status: DYNAMIC
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdncgi/beacon/expect-ct"
alt-svc: h3-25=":443"; ma=86400, h3-24=":443"; ma=86400, h3-23=":443"; ma=86400
server: cloudflare
cf-ray: 5697b1ac1862eb41-LAX
{"ip": "111.199.187.36", "country": "北京市", "city": "联通"}

范例: 利用脚本实现指定环境变量动态生成配置文件内容

[root@ubuntu1804 ~]#echo 'Nginx Website in Dockerfile' > index.html
[root@ubuntu1804 ~]#cat Dockerfile
FROM nginx:1.16-alpine
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
ENV DOC_ROOT='/data/website/'
ADD index.html ${DOC_ROOT}
ADD entrypoint.sh /bin/
EXPOSE 80/tcp 8080
#HEALTHCHECK --start-period=3s CMD wget -0 - -q http://${IP:-0.0.0.0}:
{PORT:-80}/
CMD ["/usr/sbin/nginx","-g", "daemon off;"]  #CMD指令的内容都成为了ENTRYPOINT的参数
ENTRYPOINT [ "/bin/entrypoint.sh"]
[root@ubuntu1804 ~]#cat entrypoint.sh
#!/bin/sh
cat > /etc/nginx/conf.d/www.conf <<EOF
server {
  server_name ${HOSTNAME};
  listen ${IP:-0.0.0.0}:${PORT:-80};
  root   ${DOC_ROOT:-/usr/share/nginx/html};
}
EOF
exec "$@"
[root@ubuntu1804 ~]#chmod +x entrypoint.sh
[root@ubuntu1804 ~]#docker build -t nginx:v1.0 .
[root@ubuntu1804 ~]#docker run --name n1 --rm -P -e "PORT=8080" -e
"HOSTNAME=www.magedu.org" nginx:v1.0
1.3.1.5.9 ARG: 构建参数

ARG指令在build 阶段指定变量,和ENV不同的是,容器运行时不会存在这些环境变量

ARG <name>[=<default value>]

如果和ENV同名,ENV覆盖ARG变量 可以用 docker build --build-arg <参数名>=<值> 来覆盖 范例:

[root@ubuntu1804 ~]#cat Dockerfile
FROM busybox
ARG author="wang <root@wangxiaochun.com>"
LABEL maintainer="${author}"
[root@ubuntu1804 ~]#docker build --build-arg author="29308620@qq.com" -t
busybox:v1.0

说明: ARG 和 FROM

#FROM指令支持由第一个FROM之前的任何ARG指令声明的变量
#示例:
ARG  CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD /code/run-app
FROM extras:${CODE_VERSION}
CMD /code/run-extras
#在FROM之前声明的ARG在构建阶段之外,所以它不能在FROM之后的任何指令中使用。 要使用在第一个FROM
之前声明的ARG的默认值,请在构建阶段内使用没有值的ARG指令
#示例:
ARG VERSION=latest
FROM busybox:$VERSION
ARG VERSION
RUN echo $VERSION > image_version
1.3.1.5.11 VOLUME: 匿名卷

在容器中创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等,一般会将宿主机上的目录挂载至VOLUME 指令指定的容器目录。即使容器后期被删除,此宿主机的目录仍会保留,从而实现容器数据的持久保存。

宿主机目录为

/var/lib/docker/volumes/<volume_id>/_data

语法:

VOLUME <容器内路径>
VOLUME ["<容器内路径1>", "<容器内路径2>"...]

注意:

  • Dockerfile中的VOLUME实现的是匿名数据卷,无法指定宿主机路径和容器目录的挂载关系

  • 通过docker rm -fv <容器ID> 可以删除容器的同时删除VOLUME指定的卷

范例: 在容器创建两个/data/ ,/data2的挂载点

VOLUME [ "/data1","/data2" ]  

范例:

[root@centos8 ~]#cat /data/dockerfile/system/alpine/Dockerfile 
FROM alpine:3.11
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
COPY repositories /etc/apk/repositories
VOLUME [ "/testdata","/testdata2" ]
[root@centos8 alpine]#podman run -it --rm 8ef61dd3959da3f sh
/ # df
Filesystem           1K-blocks     Used Available Use% Mounted on
overlay              104806400   3656380 101150020   3% /
tmpfs                    65536         0     65536   0% /dev
/dev/sda2            104806400   3656380 101150020   3% /testdata2
/dev/sda2            104806400   3656380 101150020   3% /testdata
/ # cp /etc/issue /testdata/f1.txt
/ # cp /etc/issue /testdata2/f2.txt
[root@centos8 ~]#tree /var/lib/containers/storage/volumes/
/var/lib/containers/storage/volumes/
├── 725f0f67921bdbffbe0aaf9b015d663a6e3ddd24674990d492025dfcf878529b
│   └── _data
│       └── f1.txt
└── fbd13e5253deb375e0dea917df832d2322e96b04ab43bae061584dcdbe7e89f2
  └── _data
      └── f2.txt
4 directories, 2 files
1.3.1.5.12 EXPOSE: 暴露端口

指定服务端的容器需要对外暴露(监听)的端口号,以实现容器与外部通信。

EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会真正暴露端口,即不会自动在宿主进行端口映射

因此,在启动容器时需要通过 -P 或-p ,Docker 主机才会真正分配一个端口转发到指定暴露的端口才可 使用

注意: 即使 Dockerfile没有EXPOSE 端口指令,也可以通过docker run -p 临时暴露容器内程序真正监听的端口,所以EXPOSE 相当于指定默认的暴露端口,可以通过docker run -P 进行真正暴露

EXPOSE <port>[/ <protocol>] [<port>[/ <protocol>] ..]
   
#说明
<protocol>用于指定传输层协议,可为tcp或udp二者之一,默认为TCP协议

范例:

EXPOSE 80 443
EXPOSE 11211/udp 11211/tcp

范例:

[root@ubuntu1804 dockerfile]#pwd
/data/dockerfile
[root@ubuntu1804 dockerfile]#echo Website in Dockerfile > index.html
[root@ubuntu1804 dockerfile]#vim Dockerfile
FROM busybox
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
COPY index.html /data/website/
EXPOSE 80
[root@ubuntu1804 dockerfile]#cat build.sh
#!/bin/bash
#
TAG=$1
docker build -t test:$TAG .
[root@ubuntu1804 dockerfile]#chmod +x build.sh
[root@ubuntu1804 dockerfile]#./build.sh v1.0
[root@ubuntu1804 dockerfile]#ls
build.sh Dockerfile index.html
[root@ubuntu1804 dockerfile]#docker run --rm -P --name c1 test:v1.0 /bin/httpd
-f -h /data/website
[root@ubuntu1804 ~]#docker port c1
80/tcp -> 0.0.0.0:32773
[root@ubuntu1804 ~]#curl 127.0.0.1:32773
Website in Dockerfile
[root@ubuntu1804 ~]#docker kill c1
c1
1.3.1.5.13 WORKDIR: 指定工作目录

为后续的 RUN、CMD、ENTRYPOINT 指令配置工作目录,当容器运行后,进入容器内WORKDIR指定的默认目录

WORKDIR 指定工作目录(或称当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会自行创建

WORKDIR /path/to/workdir

范例:

#两次RUN独立运行,不在同一个目录,
RUN cd /app
RUN echo "hello" > world.txt

#如果想实现相同目录可以使用WORKDIR
WORKDIR /app
RUN echo "hello" > world.txt

可以使用多个 WORKDIR 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

则最终路径为 /a/b/c

1.3.1.5.14 ONBUILD: 子镜像引用父镜像的指令

可以用来配置当构建当前镜像的子镜像时,会自动触发执行的指令,但在当前镜像构建时,并不会执行,即延迟到子镜像构建时才执行

ONBUILD [INSTRUCTION]

例如,Dockerfile 使用如下的内容创建了镜像 image-A。

...
ONBUILD ADD http://www.magedu.com/wp-content/uploads/2017/09/logo.png /data/
ONBUILD RUN rm -rf /*
ONBUILD RUN /usr/local/bin/python-build --dir /app/src...

如果基于 image-A 创建新的镜像image-B时,新的Dockerfile中使用 FROM image-A指定基础镜像时,会自动执行ONBUILD 指令内容,等价于在后面添加了两条指令。

FROM image-A
#Automatically run the following
ADD http://www.magedu.com/wp-content/uploads/2017/09/logo.png /data
RUN /usr/local/bin/python-build --dir /app/src

说明:

  • 尽管任何指令都可注册成为触发器指令,但ONBUILD不能自我能套,且不会触发FROM和MAINTAINER指令

  • 使用 ONBUILD 指令的镜像,推荐在标签中注明,例如 ruby:1.9-onbuild

1.3.1.5.15 USER: 指定当前用户

指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户

当服务不需要管理员权限时,可以通过该命令指定运行用户

这个用户必须是事先建立好的,否则无法切换

如果没有指定 USER,默认是 root 身份执行

USER <user>[:<group>] 
USER <UID>[:<GID>]

范例:

RUN groupadd -r mysql && useradd -r -g mysql mysqlUSER mysql
1.3.1.5.16 HEALTHCHECK: 健康检查

检查容器的健康性

HEALTHCHECK [选项] CMD <命令> #设置检查容器健康状况的命令
HEALTHCHECK NONE #如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
HEALTHCHECK 支持下列选项:  
--interval=<间隔>  #两次健康检查的间隔,默认为 30 秒
--timeout=<时长>    #健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默
认 30 秒
--retries=<次数>    #当连续失败指定次数后,则将容器状态视为 unhealthy,默认3次
--start-period=<FDURATION> #default: 0s
#检查结果返回值:
0  #success   the container is healthy and ready for use
1  #unhealth   the container is not working correctly
2  #reserved   do not use this exit code

范例:

FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s \
CMD curl -fs http://localhost/ || exit 1
1.3.1.5.17 STOPSIGNAL: 退出容器的信号

该 STOPSIGNAL 指令设置将被发送到容器退出的系统调用信号。该信号可以是与内核syscall表中的位置匹配的有效无符号数字(例如9),也可以是SIGNAME格式的信号名称(例如SIGKILL)

STOPSIGNAL signal
1.3.1.5.18 SHELL : 指定shell

SHELL指令允许覆盖用于命令的shell形式的默认SHELL, 必须在Dockerfile中以JSON形式编写SHELL指令。

SHELL ["executable", "parameters"]

在Linux上默认SHELL程序为[“/bin/sh”,“-c”],在Windows上,默认SHELL程序为[“cmd”,“/S”,“/C”]。

SHELL指令在Windows上特别有用,在Windows上有两个常用且完全不同的本机SHELL:cmd和powershell,以及包括sh在内的备用shell。

SHELL指令可以出现多次。 每个SHELL指令将覆盖所有先前的SHELL指令,并影响所有后续的指令

FROM microsoft/windowsservercore
# Executed as cmd /S /C echo default

RUN echo default
# Executed as cmd /S /C powershell -command Write-Host default

RUN powershell -command Write-Host default
# Executed as powershell -command Write-Host hello

SHELL ["powershell", "-command"]
RUN Write-Host hello

# Executed as cmd /S /C echo hello
SHELL ["cmd", "/S", "/C"]
RUN echo hello
1.3.1.5.18 .dockerignore文件

官方文档: https://docs.docker.com/engine/reference/builder/#dockerignore-file与.gitignore文件类似,生成构建上下文时Docker客户端应忽略的文件和文件夹指定模式

.dockerignore 使用 Go 的文件路径规则 filepath.Match

参考链接: https://golang.org/pkg/path/filepath/#Match

完整的语法

#     #以#开头的行为注释
*     #匹配任何非分隔符字符序列
?     #匹配任何单个非分隔符
\\    #表示 \
**    #匹配任意数量的目录(包括零)例如,**/*.go将排除在所有目录中以.go结尾的所有文件,包括构
建上下文的根。
!     #表示取反,可用于排除例外情况
RuleBehavior
# comment Ignored.
/temp Exclude files and directories whose names start with temp in any immediate subdirectory of the root. For example, the plain file /somedir/temporary.txt is excluded, as is the directory /somedir/temp .
//temp* Exclude files and directories starting with temp from any subdirectory that is two levels below the root. For example, /somedir/subdir/temporary.txt is excluded.
//temp* Exclude files and directories starting with temp from any subdirectory that is two levels below the root. For example, /somedir/subdir/temporary.txt is excluded.

范例:

#排除 test 目录下的所有文件
test/*
#排除 md 目录下的 xttblog.md 文件
md/xttblog.md
#排除 xttblog 目录下的所有 .md 的文件
xttblog/*.md
#排除以 xttblog 为前缀的文件和文件夹
xttblog?
#排除所有目录下的 .sql 文件夹
**/*.sql

范例:

#除了README的md不排外,排除所有md文件,但不排除README-secret.md
*.md
!README*.md
README-secret.md
#除了所有README的md文件以外的md都排除
*.md
README-secret.md
!README*.md
1.3.1.5.19 Dockerfile 构建过程和指令总结
  • Dockerfile 构建过程

  • 从基础镜像运行一个容器

  • 执行一条指令,对容器做出修改

  • 执行类似docker commit的操作,提交一个新的中间镜像层(可以利用中间层镜像创建容器进行调试和排错)

  • 再基于刚提交的镜像运行一个新容器

  • 执行Dockerfile中的下一条指令,直至所有指令执行完毕

Dockerfile 指令总结

image-20211204105141761

1.3.1.6 构建镜像docker build 命令

docker build命令使用Dockerfile文件创建镜像

docker build [OPTIONS] PATH | URL | -
说明:  
PATH | URL | -     #可以使是本地路径,也可以是URL路径。若设置为 - ,则从标准输入获取
Dockerfile的内容
-f, --file string  #Dockerfile文件名,默认为 PATH/Dockerfile
--force-rm   #总是删除中间层容器,创建镜像失败时,删除临时容器
--no-cache   #不使用之前构建中创建的缓存
-q  --quiet=false  #不显示Dockerfile的RUN运行的输出结果
--rm=true   #创建镜像成功时,删除临时容器
-t --tag list   #设置注册名称、镜像名称、标签。格式为 <注册名称>/<镜像名称>:<标签>(标
签默认为latest)

范例:

docker build .
docker build /usr/local/src/nginx
docker build -f /path/to/a/Dockerfile .
docker build -t shykes/myapp .
docker build -t shykes/myapp:1.0.2 -t shykes/myapp:latest .
docker build -t test/myapp .
docker build -t nginx:v1 /usr/local/src/nginx

查看镜像的构建历史: docker history 镜像ID

范例:

[root@centos8 ~]#podman history 90201858b1fc
ID             CREATED         CREATED BY                                    
SIZE     COMMENT
90201858b1fc   17 minutes ago   /bin/sh -c #(nop) CMD ["tail" ,"-f","/etc/...  
0B        
<missing>      2 hours ago     /bin/sh -c apt-get update && apt-get insta...  
14.83MB  
<missing>      35 hours ago     /bin/sh -c #(nop) CMD ["/bin/bash"]            
14.83MB  
<missing>      35 hours ago     /bin/sh -c mkdir -p /run/systemd && echo '...  
3.072kB  
<missing>      35 hours ago     /bin/sh -c set -xe && echo '#!/bin/sh' > /...  
15.87kB  
<missing>      35 hours ago     /bin/sh -c [ -z "$(apt-get indextargets)" ]    
991.2kB  
<missing>      35 hours ago     /bin/sh -c #(nop) ADD file:91a750fb184711f...  
65.58MB

范例: 利用Dockerfile构建基于CentOS的nginx镜像

[root@ubuntu1804 ~]#vim /data/Dockerfile 
[root@ubuntu1804 ~]#cat /data/Dockerfile
FROM centos
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
RUN yum install -y nginx && echo Nginx Website in Docker >
/usr/share/nginx/html/index.html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
#ENTRYPOINT ["nginx", "-g", "daemon off;"]
[root@ubuntu1804 ~]#docker build -t nginx_centos8.2:v1.14.1 /data/
Sending build context to Docker daemon  209.2MB
Step 1/6 : FROM centos
---> 831691599b88
Step 2/6 : LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
---> Running in 3fc4487e80f9
Removing intermediate container 3fc4487e80f9
---> 598318841b8a
Step 3/6 : RUN yum install -y nginx
---> Running in 8a6d9866e4ae
CentOS-8 - AppStream                            2.1 MB/s | 5.8 MB     00:02    
CentOS-8 - Base                                 1.8 MB/s | 2.2 MB     00:01    
CentOS-8 - Extras                               8.6 kB/s | 7.0 kB     00:00  
.......
Complete!
Removing intermediate container 8a6d9866e4ae
---> 8963fb608c33
Step 4/6 : RUN echo Nginx Website in Docker > /usr/share/nginx/html/index.html
---> Running in 04d4287aac49
Removing intermediate container 04d4287aac49
---> 9a95e56b9bc0
Step 5/6 : EXPOSE 80
---> Running in 8534523d8aa6
Removing intermediate container 8534523d8aa6
---> 23cca5737903
Step 6/6 : CMD ["nginx", "-g", "daemon off;"]
---> Running in d52fcc21444f
Removing intermediate container d52fcc21444f
---> afdaec99eb35
Successfully built afdaec99eb35
Successfully tagged nginx_centos8.2:v1.14.1
[root@ubuntu1804 ~]#docker run -d -P --name nginx-web nginx_centos8.2:v1.14.1
3faba5a49f63ab3a1b031da5e4940303b10ddf349069184597e703c572d257d8
[root@ubuntu1804 ~]#docker ps
CONTAINER ID       IMAGE                     COMMAND                 CREATED  
          STATUS             PORTS                   NAMES
3faba5a49f63       nginx_centos8.2:v1.14.1   "nginx -g 'daemon of…"   4 seconds
ago       Up 3 seconds        0.0.0.0:32775->80/tcp   nginx-web
[root@ubuntu1804 ~]#curl http://127.0.0.1/32775
curl: (7) Failed to connect to 127.0.0.1 port 80: Connection refused
[root@ubuntu1804 ~]#curl http://127.0.0.1:32775
Nginx Website in Docker
[root@ubuntu1804 ~]#curl -I http://127.0.0.1:32775
HTTP/1.1 200 OK
Server: nginx/1.14.1
Date: Wed, 22 Jul 2020 17:09:15 GMT
Content-Type: text/html
Content-Length: 24
Last-Modified: Wed, 22 Jul 2020 17:04:40 GMT
Connection: keep-alive
ETag: "5f1871a8-18"
Accept-Ranges: bytes

范例: 刷新镜像缓存重新构建新镜像

[root@ubuntu1804 ~]#cat /data/Dockerfile
FROM centos
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
RUN yum install -y nginx
RUN echo Nginx Website in Docker > /usr/share/nginx/html/index.html
#修改下面行,从下面行开始不再使用缓存
ENV REFRESH_DATA 2020-01-01
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
[root@ubuntu1804 ~]#docker build   -t nginx_centos8.2:v1.14.1 /data/
Sending build context to Docker daemon  209.2MB
Step 1/7 : FROM centos
---> 831691599b88
Step 2/7 : LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
---> Using cache
---> 598318841b8a
Step 3/7 : RUN yum install -y nginx
---> Using cache
---> 8963fb608c33
Step 4/7 : RUN echo Nginx Website in Docker > /usr/share/nginx/html/index.html
---> Using cache
---> 9a95e56b9bc0
Step 5/7 : ENV REFRESH_DATA 2020-01-01  #从此行开始不再利用缓存
---> Running in 4607ee0d0e77
Removing intermediate container 4607ee0d0e77
---> d6235889f336
Step 6/7 : EXPOSE 80
---> Running in 6924aab5c5c8
Removing intermediate container 6924aab5c5c8
---> 545393760683
Step 7/7 : CMD ["nginx", "-g", "daemon off;"]
---> Running in 345bbc6179d8
Removing intermediate container 345bbc6179d8
---> 4bafc2d0c7e0
Successfully built 4bafc2d0c7e0
Successfully tagged nginx_centos8.2:v1.14.1
#全部不利用缓存重新构建镜像
[root@ubuntu1804 ~]#docker build --no-cache -t nginx_centos8.2:v1.14.1 /data/
Sending build context to Docker daemon  209.2MB
Step 1/7 : FROM centos
---> 831691599b88
Step 2/7 : LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
---> Running in 41f2aab6657f
Removing intermediate container 41f2aab6657f
---> 091969d0ed9e
Step 3/7 : RUN yum install -y nginx
---> Running in 6e174d492348
CentOS-8 - AppStream                            4.2 MB/s | 5.8 MB     00:01    
CentOS-8 - Base                                 1.7 MB/s | 2.2 MB     00:01    
CentOS-8 - Extras                               1.2 kB/s | 7.0 kB     00:05    
Dependencies resolved.
......                              
Complete!
Removing intermediate container 6e174d492348
---> ba62ac34b951
Step 4/7 : RUN echo Nginx Website in Docker > /usr/share/nginx/html/index.html
---> Running in d6f785b28ef6
Removing intermediate container d6f785b28ef6
---> 6e15fdc84e21
Step 5/7 : ENV REFRESH_DATA 2020-06-06
---> Running in c6fd87ed95f6
Removing intermediate container c6fd87ed95f6
---> 328b8621ec36
Step 6/7 : EXPOSE 80
---> Running in 1af3d6964d81
Removing intermediate container 1af3d6964d81
---> 7c513643b182
Step 7/7 : CMD ["nginx", "-g", "daemon off;"]
---> Running in fd9216490941
Removing intermediate container fd9216490941
---> 0b2b61dd0445
Successfully built 0b2b61dd0445
Successfully tagged nginx_centos8.2:v1.14.1

1.3.2 实战案例: Dockerfile 制作基于基础镜像的Base镜像

1.3.2.1 准备目录结构,下载镜像并初始化系统

#按照业务类型或系统类型等方式划分创建目录环境,方便后期镜像比较多的时候进行分类
[root@ubuntu1804 ~]#mkdir
/data/dockerfile/{web/{nginx,apache,tomcat,jdk},system/{centos,ubuntu,alpine,deb
ian}} -p
[root@ubuntu1804 ~]#tree /data/dockerfile/
/data/dockerfile/
├── system
│   ├── alpine
│   ├── centos
│   ├── debian
│   └── ubuntu
└── web
  ├── apache
  ├── jdk
  ├── nginx
  └── tomcat
10 directories, 0 files
[root@ubuntu1804 ~]#
#下载基础镜像
[root@ubuntu1804 ~]#docker pull centos:centos7.7.1908
[root@ubuntu1804 ~]#docker images
REPOSITORY         TAG                 IMAGE ID           CREATED            
SIZE
centos             centos7.7.1908     08d05d1d5859        2 months ago      
204MB

1.3.2.2 先制作基于基础镜像的系统Base镜像

#先制作基于基础镜像的系统base镜像
[root@ubuntu1804 ~]#cd /data/dockerfile/system/centos/
#创建Dockerfile,注意可以是dockerfile,但无语法着色功能
[root@ubuntu1804 centos]#vim Dockerfile
[root@ubuntu1804 centos]#cat Dockerfile
FROM centos:centos7.7.1908
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
RUN yum -y install wget && rm -f /etc/yum.repos.d/* && wget -P /etc/yum.repos.d/
http://mirrors.aliyun.com/repo/Centos-7.repo \
  && wget -P /etc/yum.repos.d/ http://mirrors.aliyun.com/repo/epel-7.repo \
  && yum -y install vim-enhanced tcpdump lrzsz tree telnet bash-completion
net-tools wget curl bzip2 lsof zip unzip nfs-utils gcc make gcc-c++ glibc
glibc-devel pcre pcre-devel openssl openssl-devel systemd-devel zlib-devel \
  && yum clean all \
  && rm -f /etc/localtime \
  && ln -s ../usr/share/zoneinfo/Asia/Shanghai /etc/localtime
[root@ubuntu1804 centos]#vim build.sh
[root@ubuntu1804 centos]#cat build.sh
#!/bin/bash
#
docker build -t centos7-base:v1 .
[root@ubuntu1804 centos]#chmod +x build.sh
[root@ubuntu1804 centos]#./build.sh
[root@ubuntu1804 centos]#docker images
REPOSITORY         TAG                 IMAGE ID           CREATED            
SIZE
centos7-base       v1                 1ba1317e06dc        23 seconds ago    
402MB
centos             centos7.7.1908     08d05d1d5859        2 months ago      
204MB
[root@ubuntu1804 centos]#docker image history centos7-base:v1  
IMAGE               CREATED             CREATED BY                              
      SIZE               COMMENT
1ba1317e06dc        43 seconds ago     /bin/sh -c yum -y install wget && rm -f
/etc…   198MB              
6b87f2843eb9       About an hour ago   /bin/sh -c #(nop) LABEL
maintainer=wangxiao…   0B                  
08d05d1d5859        2 months ago       /bin/sh -c #(nop) CMD ["/bin/bash"]    
      0B                  
<missing>           2 months ago       /bin/sh -c #(nop) LABEL org.labelschema.sc…   0B                  
<missing>           2 months ago       /bin/sh -c #(nop) ADD
file:3e2a127b44ed01afc…   204MB

1.3.3 实战案例: Dockerfile 制作基于Base镜像的 nginx 镜像

1.3.3.1 在Dockerfile目录下准备编译安装的相关文件

[root@ubuntu1804 ~]#mkdir /data/dockerfile/web/nginx/1.16
[root@ubuntu1804 ~]#cd /data/dockerfile/web/nginx/1.16
[root@ubuntu1804 1.16]#wget http://nginx.org/download/nginx-1.16.1.tar.gz
[root@ubuntu1804 1.16]#mkdir app/
[root@ubuntu1804 1.16]#echo "Test Page in app" > app/index.html
[root@ubuntu1804 1.16]#tar zcf app.tar.gz app
[root@ubuntu1804 1.16]#ls
app app.tar.gz nginx-1.16.1.tar.gz  

1.3.3.2 在一台测试机进行编译安装同一版本的nginx 生成模版配置文件

[root@centos7 ~]#yum -y install vim-enhanced tcpdump lrzsz tree telnet bashcompletion net-tools wget bzip2 lsof tmux man-pages zip unzip nfs-utils gcc make 
gcc-c++ glibc glibc-devel pcre pcre-devel openssl openssl-devel systemd-devel
zlib-devel
[root@centos7 ~]#wget -P /usr/local/src http://nginx.org/download/nginx1.16.1.tar.gz
[root@centos7 ~]#cd /usr/local/src/
[root@centos7 src]#tar xvf nginx-1.16.1.tar.gz
[root@centos7 src]#cd nginx-1.16.1/
[root@centos7 nginx-1.16.1]#./configure --prefix=/apps/nginx && make && make
install
#将配置文件复制到nginx镜像的服务器相应目录下
[root@centos7 ~]#scp /apps/nginx/conf/nginx.conf
10.0.0.100:/data/dockerfile/web/nginx/1.16
#准备配置文件
[root@ubuntu1804 1.16]#vim /data/dockerfile/web/nginx/1.16/nginx.conf
worker_processes  1;
user nginx;
daemon off;   #增加此行,前台运行nginx

1.3.3.3 编写Dockerfile文件

[root@ubuntu1804 ~]#cd /data/dockerfile/web/nginx
[root@ubuntu1804 nginx]#vim Dockerfile
[root@ubuntu1804 nginx]#cat Dockerfile
FROM centos7-base:v1
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
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 \
  && rm -f /usr/local/src/nginx* \
  && useradd -r nginx
COPY nginx.conf /apps/nginx/conf/
ADD app.tar.gz /apps/nginx/html/
EXPOSE 80 443
CMD ["/apps/nginx/sbin/nginx"]
[root@ubuntu1804 nginx]#

1.3.3.4 生成nginx镜像

[root@ubuntu1804 ~]#cd /data/dockerfile/web/nginx/1.16
[root@ubuntu1804 1.16]#ls
app app.tar.gz build.sh Dockerfile nginx-1.16.1.tar.gz nginx.conf
[root@ubuntu1804 1.16]#vim build.sh
[root@ubuntu1804 1.16]#cat build.sh
#!/bin/bash
#
docker build -t nginx-centos7:1.6.1 .
[root@ubuntu1804 1.16]#chmod +x build.sh
[root@ubuntu1804 1.16]#./build.sh
[root@ubuntu1804 1.16]##docker images
REPOSITORY         TAG                 IMAGE ID           CREATED            
SIZE
nginx-centos7       1.6.1               73e4b4b95bca        10 minutes ago    
412MB
centos7-base       v1                 1ba1317e06dc       About an hour ago  
402MB
centos             centos7.7.1908     08d05d1d5859        2 months ago      
204MB

1.3.3.5 生成的容器测试镜像

[root@ubuntu1804 ~]#docker run -d -p 80:80 nginx-centos7:1.6.1
e8e733c6dc96bfb212a15dec04cfcfcac72daf400f5d2423c707aeb778a1859d
[root@ubuntu1804 ~]#docker ps
CONTAINER ID       IMAGE                 COMMAND                 CREATED      
      STATUS             PORTS                         NAMES
e8e733c6dc96       centos7-nginx:1.6.1   "/apps/nginx/sbin/ng…"   4 seconds ago
      Up 2 seconds        0.0.0.0:80->80/tcp, 443/tcp   cool_germain
[root@ubuntu1804 ~]#docker exec -it e8e733c6dc96 bash
[root@e8e733c6dc96 /]# ps aux
USER       PID %CPU %MEM   VSZ   RSS TTY     STAT START   TIME COMMAND
root          1  0.2  0.2  20572  2468 ?       Ss   03:36   0:00 nginx: master
process /apps/nginx/sbin/nginx
nginx        12  0.0  0.2  21024  2344 ?       S    03:36   0:00 nginx: worker
process
root         13  4.0  0.3  12364  3536 pts/0   Ss   03:37   0:00 bash
root         32  0.0  0.3  51764  3460 pts/0   R+   03:37   0:00 ps aux
[root@e8e733c6dc96 /]# exit
exit
[root@ubuntu1804 ~]#curl 127.0.0.1/app/
Test Page in app

1.3.4 实战案例: Dockerfile 直接制作 nginx 镜像

1.3.4.1 在Dockerfile目录下准备编译安装的相关文件

[root@ubuntu1804 ~]#mkdir /data/dockerfile/web/nginx/1.16.1
[root@ubuntu1804 ~]#cd /data/dockerfile/web/nginx/1.16.1
[root@ubuntu1804 1.16.1]#vim nginx.conf
user nginx;
worker_processes  1;
#daemon off;
[root@ubuntu1804 1.16.1]#wget http://nginx.org/download/nginx-1.16.1.tar.gz

1.3.4.2 编写Dockerfile文件

[root@ubuntu1804 1.16.1]#pwd
/data/dockerfile/web/nginx/1.16.1
[root@ubuntu1804 1.16.1]#vim Dockerfile
[root@ubuntu1804 1.16.1]#cat Dockerfile
#Nginx Dockerfile
FROM centos:centos7.7.1908
MAINTAINER wangxiaochun <root@wangxiaochun.com>
RUN yum install -y  gcc gcc-c++ pcre pcre-devel zlib zlib-devel openssl
openssl-devel \
  && useradd -r -s /sbin/nologin nginx \
  && yum clean all
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 \
  && rm -rf /usr/local/src/nginx*
  ADD nginx.conf /apps/nginx/conf/nginx.conf
COPY index.html /apps/nginx/html/
RUN ln -s /apps/nginx/sbin/nginx /usr/sbin/nginx
EXPOSE 80 443
CMD ["nginx","-g","daemon off;"]

1.3.4.3 生成nginx镜像

[root@ubuntu1804 ~]#cd /data/dockerfile/web/nginx/1.16.1
[root@ubuntu1804 1.16.1]#vim build.sh
[root@ubuntu1804 1.16.1]#cat build.sh
#!/bin/bash
#
docker build -t nginx-centos7:1.6.1-v2 .
[root@ubuntu1804 1.16.1]#chmod +x build.sh
[root@ubuntu1804 1.16.1]#ls
build.sh Dockerfile index.html nginx-1.16.1.tar.gz nginx.conf
[root@ubuntu1804 1.16.1]#./build.sh
[root@ubuntu1804 1.16.1]#docker images
REPOSITORY         TAG                 IMAGE ID           CREATED            
SIZE
nginx-centos7       1.6.1-v2           1918d29d5f45        17 minutes ago    
328MB
nginx-centos7       1.6.1               8c16774437a5        13 hours ago      
412MB
centos7-base       v1                 1ba1317e06dc        15 hours ago      
402MB
centos             centos7.7.1908     08d05d1d5859        2 months ago      
204MB

1.3.4.4 生成容器测试镜像

[root@ubuntu1804 ~]#docker run -d -p 80:80 nginx-centos7:1.6.1-v2 
21c954ad4fb902076832cc9a52dd1502aca43d9bcd2b46a2f164382e4ac7b3f6
[root@ubuntu1804 ~]#docker ps
CONTAINER ID       IMAGE                   COMMAND                 CREATED  
          STATUS             PORTS                         NAMES
21c954ad4fb9       centos7-nginx:1.6.1-v2   "nginx -g 'daemon of…"   6 seconds
ago       Up 4 seconds        0.0.0.0:80->80/tcp, 443/tcp   inspiring_goldwasser
[root@ubuntu1804 ~]#curl 127.0.0.1
Test Page v2 in Docker
[root@ubuntu1804 ~]#docker exec -it 21c954ad4fb9 bash
[root@21c954ad4fb9 /]# ps aux
USER       PID %CPU %MEM   VSZ   RSS TTY     STAT START   TIME COMMAND
root          1  0.5  0.2  20572  2372 ?       Ss   03:30   0:00 nginx: master
process nginx -g daemon off;
nginx         6  0.0  0.2  21024  2316 ?       S    03:30   0:00 nginx: worker
process
root          7 11.5  0.2  11840  2880 pts/0   Ss   03:31   0:00 bash
root         20  0.0  0.3  51764  3376 pts/0   R+   03:31   0:00 ps aux
[root@21c954ad4fb9 /]# exit
exit

2.4 生产案例: 制作自定义tomcat业务镜像

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

2.4.1 自定义 Centos 系统基础镜像

先基于官方提供的基础镜像,制作出安装了常用命令的自定义基础镜像

[root@ubuntu1804 ~]#docker pull centos:centos7.7.1908
[root@ubuntu1804 ~]#mkdir -p
/data/dockerfile/{web/{nginx,tomcat,jdk},system/{centos,ubuntu,alpine,debian}}
[root@ubuntu1804 ~]#cd /data/dockerfile/system/centos/
[root@ubuntu1804 centos]#vim Dockerfile
[root@ubuntu1804 centos]#cat Dockerfile  
# Centos Base Image
FROM centos:centos7.7.1908
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
RUN yum -y install wget && rm -f /etc/yum.repos.d/* && wget -P /etc/yum.repos.d/
http://mirrors.aliyun.com/repo/Centos-7.repo \
  && wget -P /etc/yum.repos.d/ http://mirrors.aliyun.com/repo/epel-7.repo \
  && yum -y install vim-enhanced tcpdump lrzsz tree telnet bash-completion
net-tools wget bzip2 lsof zip unzip nfs-utils gcc make gcc-c++ glibc glibcdevel pcre pcre-devel openssl openssl-devel systemd-devel zlib-devel \
  && yum clean all \
  && rm -f /etc/localtime \
  && ln -s ../usr/share/zoneinfo/Asia/Shanghai /etc/localtime
#添加系统账户
RUN groupadd www -g 2019 && useradd www -u 2019 -g www
[root@ubuntu1804 centos]#vim build.sh
#通过脚本构建镜像
[root@ubuntu1804 centos]#cat build.sh  
#!/bin/bash
docker build -t centos7-base:v1 .
[root@ubuntu1804 centos]#bash build.sh
[root@ubuntu1804 centos]#docker images
REPOSITORY         TAG                 IMAGE ID           CREATED            
SIZE
centos7-base       v1                 34ab3afcd3b3        4 seconds ago      
403MB
centos             centos7.7.1908     08d05d1d5859        2 months ago      
204MB

2.4.2 构建JDK 镜像

2.4.2.1 上传JDK压缩包和profile文件上传到Dockerfile当前目录

#将CentOS7主机上的/etc/profile文件传到 Dockerfile 所在目录下
[root@ubuntu1804 ~]#scp centos7:/etc/profile 10.0.0.100:/data/dockerfile/web/jdk
#修改profile文件,加下面四行相关变量
[root@ubuntu1804 ~]#vim /data/dockerfile/web/jdk/profile
[root@ubuntu1804 ~]#tail -n 5 /data/dockerfile/web/jdk/profile
export JAVA_HOME=/usr/local/jdk
export TOMCAT_HOME=/apps/tomcat
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$TOMCAT_HOME/bin:$PATH
export
CLASSPATH=.$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar
#下载jdk文件传到Dockfile目录下
#https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads2133151.html
[root@ubuntu1804 ~]#tree /data/dockerfile/web/jdk
/data/dockerfile/web/jdk
├── jdk-8u212-linux-x64.tar.gz
└── profile
0 directories, 2 files

2.4.2.2 准备Dockerfile文件

[root@ubuntu1804 ~]#vim /data/dockerfile/web/jdk/Dockerfile 
[root@ubuntu1804 ~]#cat /data/dockerfile/web/jdk/Dockerfile
#JDK Base Image
FROM centos7-base:v1
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
ADD jdk-8u212-linux-x64.tar.gz /usr/local/src/
RUN ln -s /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

2.4.2.3 执行构建脚本制作镜像

[root@ubuntu1804 ~]#vim /data/dockerfile/web/jdk/build.sh
[root@ubuntu1804 ~]#cat /data/dockerfile/web/jdk/build.sh
#!/bin/bash
docker build -t centos7-jdk:8u212 .
[root@ubuntu1804 ~]#tree /data/dockerfile/web/jdk/
/data/dockerfile/web/jdk/
├── build.sh
├── Dockerfile
├── jdk-8u212-linux-x64.tar.gz
└── profile
0 directories, 4 files
[root@ubuntu1804 ~]#cd /data/dockerfile/web/jdk/
[root@ubuntu1804 jdk]#bash build.sh
[root@ubuntu1804 jdk]#docker images
REPOSITORY         TAG                 IMAGE ID           CREATED            
SIZE
centos7-jdk         8u212               fdbeb8a49ea6        59 seconds ago    
809MB
centos7-base       v1                 34ab3afcd3b3        44 minutes ago    
403MB
centos             centos7.7.1908     08d05d1d5859        2 months ago      
204MB

2.3.4.4 从镜像启动容器测试

[root@ubuntu1804 jdk]#docker run -it --rm centos7-jdk:8u212 bash
[root@25c9c0266bd2 /]# 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)

2.4.3 从JDK镜像构建tomcat 8 Base镜像

基于自定义的 JDK 基础镜像,构建出通用的自定义 Tomcat 基础镜像,此镜像后 期会被多个业务的多个服务共同引用(相同的JDK 版本和Tomcat 版本)

2.4.3.1 上传tomcat 压缩包

[root@ubuntu1804 ~]#mkdir -p /data/dockerfile/web/tomcat/tomcat-base-8.5.50
[root@ubuntu1804 ~]#cd /data/dockerfile/web/tomcat/tomcat-base-8.5.50
[root@ubuntu1804 tomcat-base-8.5.50]#
wget http://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat8/v8.5.50/bin/apache-tomcat-8.5.50.tar.gz

2.4.3.2 编辑Dockerfile

[root@ubuntu1804 ~]#cat /data/dockerfile/web/tomcat/tomcat-base8.5.50/Dockerfile 
#Tomcat Base Image
FROM centos7-jdk:8u212
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
#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.50
ENV CATALINA_HOME /apps/tomcat
ENV APP_DIR ${CATALINA_HOME}/webapps
RUN mkdir /apps  
ADD apache-tomcat-8.5.50.tar.gz /apps  
RUN ln -s /apps/apache-tomcat-8.5.50 /apps/tomcat

2.4.3.3 通过脚本构建tomcat 基础镜像

[root@ubuntu1804 tomcat-base-8.5.50]#vim build.sh 
[root@ubuntu1804 tomcat-base-8.5.50]#cat build.sh
#!/bin/bash
docker build -t tomcat-base:v8.5.50 .
[root@ubuntu1804 tomcat-base-8.5.50]#tree
.
├── apache-tomcat-8.5.50.tar.gz
├── build.sh
└── Dockerfile
0 directories, 3 files
[root@ubuntu1804 tomcat-base-8.5.50]#docker images
REPOSITORY         TAG                 IMAGE ID           CREATED            
SIZE
tomcat-base         v8.5.50             8d5395cb72c4        3 seconds ago      
824MB
centos7-jdk         8u212               e0fe770a7ccd        22 minutes ago    
809MB
centos7-base       v1                 34ab3afcd3b3        2 hours ago        
403MB
centos             centos7.7.1908     08d05d1d5859        2 months ago      
204MB

2.4.3.4 验证镜像构建完成

[root@ubuntu1804 tomcat-base-8.5.50]#docker run -it --rm -p 8080:8080 tomcatbase:v8.5.50 bash   
[root@d0a387e0ccc9 /]# /apps/tomcat/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/tomcatjuli.jar
Tomcat started.
[root@d0a387e0ccc9 /]# netstat -ntl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 0.0.0.0:8009            0.0.0.0:*               LISTEN    
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN    
[root@d0a387e0ccc9 /]#

2.4.4 构建业务镜像1

创建tomcat-app1和tomcat-app2两个目录,代表不同的两个基于tomcat的业务。

2.4.4.1 准备tomcat的配置文件

[root@ubuntu1804 ~]#mkdir -p /data/dockerfile/web/tomcat/tomcat-app{1,2}
[root@ubuntu1804 ~]#tree /data/dockerfile/web/tomcat/
/data/dockerfile/web/tomcat/
├── tomcat-app1
├── tomcat-app2
└── tomcat-base-8.5.50
  ├── apache-tomcat-8.5.50.tar.gz
  ├── build.sh
  └── Dockerfile
3 directories, 3 files

#上传和修改server.xml
[root@ubuntu1804 ~]#cd /data/dockerfile/web/tomcat/tomcat-base-8.5.50
[root@ubuntu1804 tomcat-base-8.5.50]#tar xf apache-tomcat-8.5.50.tar.gz
[root@ubuntu1804 tomcat-base-8.5.50]#cp apache-tomcat-8.5.50/conf/server.xml
/data/dockerfile/web/tomcat/tomcat-app1/
[root@ubuntu1804 tomcat-base-8.5.50]#cd /data/dockerfile/web/tomcat/tomcat-app1/
[root@ubuntu1804 tomcat-app1]#vim server.xml
......
<Host name="localhost"  appBase="/data/tomcat/webapps"                        
   
           unpackWARs="true" autoDeploy="true">
......

image-20211204214243512

2.4.4.2 准备自定义页面

[root@ubuntu1804 tomcat-app1]#mkdir app
[root@ubuntu1804 tomcat-app1]#echo "Tomcat Page in app1" > app/index.jsp
[root@ubuntu1804 tomcat-app1]#tar zcf app.tar.gz app

2.4.4.3 准备容器启动执行脚本

[root@ubuntu1804 tomcat-app1]#vim run_tomcat.sh
[root@ubuntu1804 tomcat-app1]#cat run_tomcat.sh
#!/bin/bash
echo "nameserver 180.76.76.76" > /etc/resolv.conf
su - www -c "/apps/tomcat/bin/catalina.sh start"
su - www -c "tail -f /etc/hosts"
[root@ubuntu1804 tomcat-app1]#chmod a+x run_tomcat.sh

2.4.4.4 准备Dockerfile

[root@ubuntu1804 tomcat-app1]#vim Dockerfile
[root@ubuntu1804 tomcat-app1]#cat Dockerfile
#Tomcat Web Image
FROM tomcat-base:v8.5.50
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
ADD server.xml /apps/tomcat/conf/server.xml
ADD run_tomcat.sh /apps/tomcat/bin/run_tomcat.sh
ADD app.tar.gz /data/tomcat/webapps/
RUN chown -R www.www /apps/   /data/tomcat/  
EXPOSE 8080  8009
CMD ["/apps/tomcat/bin/run_tomcat.sh"]

2.4.4.5 执行构建脚本制作镜像

[root@ubuntu1804 tomcat-app1]#vim build.sh
[root@ubuntu1804 tomcat-app1]#cat build.sh
#!/bin/bash
docker build -t tomcat-web:app1 .
[root@ubuntu1804 tomcat-app1]#pwd
/data/dockerfile/web/tomcat/tomcat-app1
[root@ubuntu1804 tomcat-app1]#tree
.
├── app
│   └── index.jsp
├── app.tar.gz
├── build.sh
├── Dockerfile
├── run_tomcat.sh
└── server.xml
1 directory, 6 files
[root@ubuntu1804 tomcat-app1]#bash build.sh
[root@ubuntu1804 tomcat-app1]#docker images
REPOSITORY         TAG                 IMAGE ID           CREATED            
SIZE
tomcat-web         app1               3e9eacc5ef86        4 seconds ago      
824MB
tomcat-base         v8.5.50             8d5395cb72c4        35 minutes ago    
824MB
centos7-jdk         8u212               e0fe770a7ccd        57 minutes ago    
809MB
centos7-base       v1                 34ab3afcd3b3        2 hours ago        
403MB
centos             centos7.7.1908     08d05d1d5859        2 months ago      
204MB

2.4.4.6 从镜像启动测试容器

[root@ubuntu1804 tomcat-app1]#docker run -d -p 8080:8080 tomcat-web:app1
82e6690e36c3a6faf2dae62bd706a89cbba490d567c841c37501f0fba670ea25

2.4.4.7 访问测试

[root@ubuntu1804 ~]#curl 127.0.0.1:8080/app/
Tomcat Page in app1
[root@ubuntu1804 ~]#docker exec -it 82e6690e36c3 bash
[root@82e6690e36c3 /]# ps aux
USER       PID %CPU %MEM   VSZ   RSS TTY     STAT START   TIME COMMAND
root          1  0.0  0.2  15136  2248 ?       Ss   22:14   0:00 /bin/bash
/apps/tomcat/bin/run_tomcat.sh
www          25  0.8  9.7 2241656 95924 ?       Sl   22:14   0:04
/usr/local/jdk/bin/java -Djava.util.logging.config.file=/apps/tomcat
root         26  0.0  0.4  85428  4472 ?       S    22:14   0:00 su - www -c
tail -f /etc/hosts
www          27  0.0  0.0   4416   720 ?       Ss   22:14   0:00 tail -f
/etc/hosts
root         82 25.0  0.3  15800  3820 pts/0   Ss   22:22   0:00 bash
root        101  0.0  0.3  55196  3836 pts/0   R+   22:22   0:00 ps aux
[root@82e6690e36c3 /]# vim /data/tomcat/webapps/app/index.jsp
[root@82e6690e36c3 /]# cat /data/tomcat/webapps/app/index.jsp
Tomcat Page in app1 v2
[root@82e6690e36c3 /]# /apps/tomcat/bin/catalina.sh stop
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/tomcatjuli.jar
[root@82e6690e36c3 /]# /apps/tomcat/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/tomcatjuli.jar
Tomcat started.
[root@ubuntu1804 tomcat-app1]#curl 127.0.0.1:8080/app/
Tomcat Page in app1 v2

2.4.4 构建业务镜像2

2.4.4.1 准备自定义页面和其它数据

[root@ubuntu1804 tomcat]#pwd
/data/dockerfile/web/tomcat
[root@ubuntu1804 tomcat]#cp -a tomcat-app1/* tomcat-app2/
[root@ubuntu1804 tomcat]#tree tomcat-app2/
tomcat-app2/
├── app
│   └── index.jsp
├── app.tar.gz
├── build.sh
├── Dockerfile
├── run_tomcat.sh
└── server.xml
1 directory, 6 files
[root@ubuntu1804 tomcat]#cd tomcat-app2
[root@ubuntu1804 tomcat-app2]#echo "Tomcat Page in app2" > app/index.html
[root@ubuntu1804 tomcat-app2]#rm -f app.tar.gz
[root@ubuntu1804 tomcat-app2]#tar zcf app.tar.gz app

2.4.4.2 准备容器启动脚本run_tomcat.sh

和业务1一样不变

2.4.4.3 准备Dockerfile

和业务1一样不变

2.4.4.4 执行构建脚本制作镜像





posted @   爬上山丘  阅读(288)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示