Docker命令与镜像制作-Dya 02

1 Docker容器管理

1.1 语法格式

docker run [选项] [镜像名] [shell命令] [参数]
docker run [参数选项] [镜像名称,必须在所有选项的后面] [/bin/echo 'hellowold'] #单次执行,没有自定义容器名称
docker run centos /bin/echo 'hello wold' #启动的容器在执行完shel命令就退出了

1.2 启动一个容器

[root@test01 ~]# docker run -it alpine:latest /bin/sh # -i:交互式操作。-t: 分配一个tty终端
/ # exit  # 在容器中退出的话,像这种没有守护进程的镜像,容器也会退出运行
[root@test01 ~]# docker ps -l
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
78af0f97e239        alpine:latest       "/bin/sh"           11 seconds ago      Exited (0) 3 seconds ago                       cool_diffie

# 退出容器命令行,容器继续运行
[root@test01 ~]# docker run -it alpine:latest /bin/sh  # 在容器命令行按 ctrl+p+q,就可以退出容器命令行,容器继续运行
/ # [root@test01 ~]# docker ps -l
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
d1217afbf527        alpine:latest       "/bin/sh"           16 seconds ago      Up 15 seconds                           friendly_lumiere

1.3 查看容器

1.3.1 查看正在运行的容器

[root@test01 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
d1217afbf527        alpine:latest       "/bin/sh"                2 minutes ago       Up 2 minutes                             friendly_lumiere
e6e1ca6883dc        605c77e624dd        "/docker-entrypoint.…"   2 hours ago         Up 2 hours          0.0.0.0:81->80/tcp   kind_meninsky

1.3.2 查看最近启动的一个容器

[root@test01 ~]# docker ps -l
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
d1217afbf527        alpine:latest       "/bin/sh"           7 minutes ago       Up 7 minutes                            friendly_lumiere

1.3.3 查看所有容器

[root@test01 ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
d1217afbf527        alpine:latest       "/bin/sh"                8 minutes ago       Up 8 minutes                             friendly_lumiere
db2d702c166d        alpine:latest       "/bin/bash"              10 minutes ago      Created                                  stupefied_elgamal
5dd07a6914cd        alpine:latest       "bash"                   10 minutes ago      Created                                  admiring_ishizaka
e6e1ca6883dc        605c77e624dd        "/docker-entrypoint.…"   2 hours ago         Up 2 hours          0.0.0.0:81->80/tcp   kind_meninsky

1.4 删除容器

1.4.1 删除未运行的容器

[root@test01 ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
d1217afbf527        alpine:latest       "/bin/sh"                9 minutes ago       Up 9 minutes                             friendly_lumiere
db2d702c166d        alpine:latest       "/bin/bash"              11 minutes ago      Created                                  stupefied_elgamal
5dd07a6914cd        alpine:latest       "bash"                   12 minutes ago      Created                                  admiring_ishizaka
e6e1ca6883dc        605c77e624dd        "/docker-entrypoint.…"   2 hours ago         Up 2 hours          0.0.0.0:81->80/tcp   kind_meninsky
[root@test01 ~]# docker rm db2d702c166d # 可以指定id或容器名进行删除。且可以一次性删除多个,容器ID或容器名之间用空格分
db2d702c166d
[root@test01 ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
d1217afbf527        alpine:latest       "/bin/sh"                10 minutes ago      Up 10 minutes                            friendly_lumiere
5dd07a6914cd        alpine:latest       "bash"                   12 minutes ago      Created                                  admiring_ishizaka
e6e1ca6883dc        605c77e624dd        "/docker-entrypoint.…"   2 hours ago         Up 2 hours          0.0.0.0:81->80/tcp   kind_meninsky

1.4.2 删除正在运行的容器

[root@test01 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
d1217afbf527        alpine:latest       "/bin/sh"                10 minutes ago      Up 10 minutes                            friendly_lumiere
e6e1ca6883dc        605c77e624dd        "/docker-entrypoint.…"   2 hours ago         Up 2 hours          0.0.0.0:81->80/tcp   kind_meninsky
[root@test01 ~]# docker rm -f d1217afbf527 # 可以指定id或容器名进行删除。且可以一次性删除多个,容器ID或容器名之间用空格分隔
d1217afbf527
[root@test01 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
e6e1ca6883dc        605c77e624dd        "/docker-entrypoint.…"   2 hours ago         Up 2 hours          0.0.0.0:81->80/tcp   kind_meninsky

1.5 容器端口映射

1.5.1 随机端口映射

-P:分配随机端口(宿主机上的)映射到容器端口
Docker随机端口范围的默认值是32768到60999。
可以通过修改/etc/sysctl.conf文件中的net.ipv4.ip_local_port_range参数来调整随机端口范围。

[root@test01 ~]# docker run -it -d -P nginx:latest
04dfa3d4a8d91d566bab247ab972e4f9905cb6e8d6f1266dd4e9365258309be1
[root@test01 ~]# docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                   NAMES
04dfa3d4a8d9        nginx:latest        "/docker-entrypoint.…"   3 seconds ago       Up 2 seconds        0.0.0.0:32769->80/tcp   stupefied_diffie

[root@test01 ~]# curl -I 10.31.200.3:32769
HTTP/1.1 200 OK
Server: nginx/1.21.5
Date: Thu, 16 Mar 2023 14:05:24 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 28 Dec 2021 15:28:38 GMT
Connection: keep-alive
ETag: "61cb2d26-267"
Accept-Ranges: bytes

# 查看iptables规则
[root@test01 ~]# iptables -t nat -vnL
Chain PREROUTING (policy ACCEPT 2 packets, 104 bytes)
 pkts bytes target     prot opt in     out     source               destination
   22  1144 DOCKER     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT 2 packets, 104 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 4 packets, 277 bytes)
 pkts bytes target     prot opt in     out     source               destination
    1    60 DOCKER     all  --  *      *       0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT 5 packets, 337 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 MASQUERADE  all  --  *      !docker0  172.17.0.0/16        0.0.0.0/0
    0     0 MASQUERADE  tcp  --  *      *       172.17.0.3           172.17.0.3           tcp dpt:80
    0     0 MASQUERADE  tcp  --  *      *       172.17.0.2           172.17.0.2           tcp dpt:80

Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 RETURN     all  --  docker0 *       0.0.0.0/0            0.0.0.0/0
    0     0 DNAT       tcp  --  !docker0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:81 to:172.17.0.3:80
    1    60 DNAT       tcp  --  !docker0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:32769 to:172.17.0.2:80  # 这里可以看到,所有请求到32769端口的,都会转到172.17.0.2:80

1.5.2 指定端口映射

1.5.2.1 方法1:本地端口映射到容器端口
[root@test01 ~]# docker run -it -d -p 999:80 nginx:latest # 999宿主机端口,80容器端口
985bd9bc30fbfaea4822fc426518b0e528970770216c2fba6174cc8b579b9bb6
[root@test01 ~]# docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                 NAMES
985bd9bc30fb        nginx:latest        "/docker-entrypoint.…"   4 seconds ago       Up 2 seconds        0.0.0.0:999->80/tcp   elegant_khayyam
[root@test01 ~]# curl -I 10.31.200.3:999
HTTP/1.1 200 OK
Server: nginx/1.21.5
Date: Thu, 16 Mar 2023 14:17:45 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 28 Dec 2021 15:28:38 GMT
Connection: keep-alive
ETag: "61cb2d26-267"
Accept-Ranges: bytes

[root@test01 ~]# iptables -t nat -vnL
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
   22  1144 DOCKER     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    2   120 DOCKER     all  --  *      *       0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT 1 packets, 60 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 MASQUERADE  all  --  *      !docker0  172.17.0.0/16        0.0.0.0/0
    0     0 MASQUERADE  tcp  --  *      *       172.17.0.3           172.17.0.3           tcp dpt:80
    0     0 MASQUERADE  tcp  --  *      *       172.17.0.2           172.17.0.2           tcp dpt:80
    0     0 MASQUERADE  tcp  --  *      *       172.17.0.4           172.17.0.4           tcp dpt:80

Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 RETURN     all  --  docker0 *       0.0.0.0/0            0.0.0.0/0
    0     0 DNAT       tcp  --  !docker0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:81 to:172.17.0.3:80
    1    60 DNAT       tcp  --  !docker0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:32769 to:172.17.0.2:80
    1    60 DNAT       tcp  --  !docker0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:999 to:172.17.0.4:80
1.5.2.2 方法2:指定宿主机ip和端口

当服务器多个IP时,可以指定某端口的请求从指定IP进来时,才被转发到容器

# 不指定地址映射,外部所有请求都可以请求到容器
[root@test01 ~]# ss -lntup|grep 999
tcp    LISTEN     0      128    [::]:999                [::]:*                   users:(("docker-proxy",pid=19422,fd=4))

# 指定地址映射
[root@test01 ~]# docker run -d -it -p 10.31.200.3:1001:80/tcp nginx:latest # 只有请求10.31.200.3:1001,才能访问到容器的80
ce4e9f636cd1c59f8c6c60be1e968f46bde228849257ac4853d686a395c164d9
[root@test01 ~]# docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                      NAMES
ce4e9f636cd1        nginx:latest        "/docker-entrypoint.…"   8 seconds ago       Up 7 seconds        10.31.200.3:1001->80/tcp   upbeat_mendel

[root@test01 ~]# ss -lnt|grep 1001
LISTEN     0      128    10.31.200.3:1001                     *:*
1.5.2.3 方法3:指定宿主机ip和随机端口
[root@test01 ~]# docker run -d -it -p 10.31.200.3::80  nginx:latest # 不写宿主机端口就是随机分配
83e34150ce61156da1acf1ea14f3afb1ed1700f4e8166c9306d0f6d886119e19
[root@test01 ~]# docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                       NAMES
83e34150ce61        nginx:latest        "/docker-entrypoint.…"   3 seconds ago       Up 2 seconds        10.31.200.3:32770->80/tcp   nervous_boot # 这里随机分配的32770
1.5.2.4 方法4:指定宿主机IP、端口、协议

默认协议为:tcp

docker run -d -it -p 10.31.200.3:93:80/tcp -p 530:53/udp nginx:latest
1.5.2.5 方法5:一次性映射多个端口和协议
[root@test01 ~]# docker run -d -it -p 80:80 -p 443:443  nginx:latest

1.5.3 直接使用宿主机端口

容器是什么端口,宿主机上就是什么端口
–network=host:host,使用宿主机的IP和端口

[root@test01 ~]# docker run -d -it --network=host nginx:latest
11fcc30bc5c4569b7a6f3c1fc7667e8f7b22fa0f543f5d0bf15c7f653e0bb3a2
[root@test01 ~]# docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
11fcc30bc5c4        nginx:latest        "/docker-entrypoint.…"   3 seconds ago       Up 2 seconds                            epic_mcclintock
[root@test01 ~]# ss -lntup|grep 80
tcp    LISTEN     0      128       *:80                    *:*                   users:(("nginx",pid=22864,fd=7),("nginx",pid=22863,fd=7),("nginx",pid=22825,fd=7))
tcp    LISTEN     0      128    [::]:80                 [::]:*                   users:(("nginx",pid=22864,fd=8),("nginx",pid=22863,fd=8),("nginx",pid=22825,fd=8))
[root@test01 ~]# curl -I 10.31.200.3
HTTP/1.1 200 OK
Server: nginx/1.21.5
Date: Fri, 17 Mar 2023 05:42:49 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 28 Dec 2021 15:28:38 GMT
Connection: keep-alive
ETag: "61cb2d26-267"
Accept-Ranges: bytes

1.5.4 查看容器已经映射的端口

[root@test01 ~]# docker ps -a  # docker ps也可以看(比较常用)
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
b5d6b01a7930        nginx:latest        "/docker-entrypoint.…"   4 seconds ago       Up 3 seconds        0.0.0.0:1000->80/tcp   elastic_goodall
11fcc30bc5c4        nginx:latest        "/docker-entrypoint.…"   32 minutes ago      Up 32 minutes                              epic_mcclintock
[root@test01 ~]# docker port b5d6b01a7930 # docker port也可以看
80/tcp -> 0.0.0.0:1000

1.6 查看容器日志

docker logs 容器名或容器ID
#参数
-f : 跟踪日志输出(实时查看)
--since :显示某个开始时间的所有日志
-t : 显示时间戳
--tail :仅列出最新N条容器日志

1.6.1 方式1:全量查看

方式1太过简单粗暴,一次查看所有日志,一般生产日志都非常多,这样会导致终端直接卡死

[root@test01 ~]# docker logs 11fcc30bc5c4
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2023/03/17 05:42:21 [notice] 1#1: using the "epoll" event method
2023/03/17 05:42:21 [notice] 1#1: nginx/1.21.5
2023/03/17 05:42:21 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
2023/03/17 05:42:21 [notice] 1#1: OS: Linux 3.10.0-1062.el7.x86_64
2023/03/17 05:42:21 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2023/03/17 05:42:21 [notice] 1#1: start worker processes
2023/03/17 05:42:21 [notice] 1#1: start worker process 31
2023/03/17 05:42:21 [notice] 1#1: start worker process 32
10.31.200.3 - - [17/Mar/2023:05:42:49 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.29.0" "-"

[root@test01 ~]# docker logs 11fcc30bc5c4|less # 这样可以防止日志全量输出,卡死终端

1.6.2 方式2:实时查看

这种方式也会一次加载所有日志内容出来,日志内容少还行,多了不推荐

[root@test01 ~]# docker logs -f 11fcc30bc5c4
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2023/03/17 05:42:21 [notice] 1#1: using the "epoll" event method
2023/03/17 05:42:21 [notice] 1#1: nginx/1.21.5
2023/03/17 05:42:21 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
2023/03/17 05:42:21 [notice] 1#1: OS: Linux 3.10.0-1062.el7.x86_64
2023/03/17 05:42:21 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2023/03/17 05:42:21 [notice] 1#1: start worker processes
2023/03/17 05:42:21 [notice] 1#1: start worker process 31
2023/03/17 05:42:21 [notice] 1#1: start worker process 32
10.31.200.3 - - [17/Mar/2023:05:42:49 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.29.0" "-"

1.6.3 方式3:查看最后几行

工作中比较推荐这种方式。
但更加合理的还是做日志收集

[root@test01 ~]# docker logs -f --tail 5 11fcc30bc5c4
2023/03/17 05:42:21 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2023/03/17 05:42:21 [notice] 1#1: start worker processes
2023/03/17 05:42:21 [notice] 1#1: start worker process 31
2023/03/17 05:42:21 [notice] 1#1: start worker process 32
10.31.200.3 - - [17/Mar/2023:05:42:49 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.29.0" "-"

1.7 自定义容器名称

容器启动时可以用–name来指定容器名,不指定的话会随机分配一个名称

[root@test01 ~]# docker run -d -it -p :80 --name nginx-v1 nginx:latest
12104a624f6b3cd165b3f1fbcab83acd2d91fe4bcb579cbb0c4a5064134adaf1
[root@test01 ~]# docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                   NAMES
12104a624f6b        nginx:latest        "/docker-entrypoint.…"   4 seconds ago       Up 2 seconds        0.0.0.0:32770->80/tcp   nginx-v1

1.8 后台运行容器

-d:让容器后台运行

[root@test01 ~]# docker run -d -it  nginx:latest
5a292ecb3cfad9264e7c3443e2505e21bee447a26524455b46111b9b675959c0
[root@test01 ~]# docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
5a292ecb3cfa        nginx:latest        "/docker-entrypoint.…"   3 seconds ago       Up 2 seconds        80/tcp              goofy_gagarin

1.8.1 为什么要后台运行

# 这里用nginx举例说明。
## nginx容器,默认是有deamon守护进程的,不加-d是这样的
[root@test01 ~]# docker run -it -p :80  nginx:latest  # 因为nginx有守护进程的原因,默认会前台运行,所以我们必须加-d让他后台运行,这样关闭终端才不会影响服务正常运行,否则容器会退出
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2023/03/17 06:22:20 [notice] 1#1: using the "epoll" event method
2023/03/17 06:22:20 [notice] 1#1: nginx/1.21.5
2023/03/17 06:22:20 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
2023/03/17 06:22:20 [notice] 1#1: OS: Linux 3.10.0-1062.el7.x86_64
2023/03/17 06:22:20 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2023/03/17 06:22:20 [notice] 1#1: start worker processes
2023/03/17 06:22:20 [notice] 1#1: start worker process 30
2023/03/17 06:22:20 [notice] 1#1: start worker process 31


# 按ctrl+c 前台运行的容器就会退出
2023/03/17 06:23:35 [notice] 1#1: signal 2 (SIGINT) received, exiting
2023/03/17 06:23:35 [notice] 1#1: signal 17 (SIGCHLD) received from 30
2023/03/17 06:23:35 [notice] 1#1: worker process 30 exited with code 0
2023/03/17 06:23:35 [notice] 1#1: signal 29 (SIGIO) received
2023/03/17 06:23:35 [notice] 1#1: signal 17 (SIGCHLD) received from 31
2023/03/17 06:23:35 [notice] 1#1: worker process 31 exited with code 0
2023/03/17 06:23:35 [notice] 1#1: exit

1.9 创建并进入容器

参数:
-i:表示在容器中保持标准输入流(STDIN)开放,使得用户可以将输入发送到容器中的命令或应用程序。
-t:表示在容器中分配一个终端操作器,以便用户可以使用交互式(TTY)模式与容器进行通信。

[root@test01 ~]# docker run -it  nginx:latest bash  # bash是传递的命令,这样可以直接进入命令行,可以使用sh。
root@7a33a99724f5:/#
root@7a33a99724f5:/#
root@7a33a99724f5:/# ls
bin  boot  dev  docker-entrypoint.d  docker-entrypoint.sh  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@7a33a99724f5:/# exit
exit
[root@test01 ~]# docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS               NAMES
7a33a99724f5        nginx:latest        "/docker-entrypoint.…"   10 seconds ago      Exited (0) 3 seconds ago                       laughing_satoshi

1.10 单次运行容器

–rm:容器退出后就自动删除

[root@localhost ~]# docker run -it --rm --name nginx-delete-test nginx # 这里运行一个容器,然后ctrl+c退出

[root@localhost ~]# docker ps -a # ps -a也找不到这个容器,就说明被删除了
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

1.10 启动容器时传递命令

容器需要有一个前台运行的进程才能保持容器的运行,通过传递运行参数是一种方式,另外也可以在构建镜像的时候指定容器启动时运行的前台命令。

[root@localhost ~]# docker run -it --name nginx-delete-test nginx 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      54d159aeed88

1.11 容器的启动和关闭

关闭:stop
启动:start
重启:restart

[root@localhost ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
3960437b729f        nginx               "/docker-entrypoint.…"   8 seconds ago       Up 7 seconds        80/tcp              nginx-delete-test
[root@localhost ~]# docker stop 3960437b729f
3960437b729f
[root@localhost ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                    PORTS               NAMES
3960437b729f        nginx               "/docker-entrypoint.…"   19 seconds ago      Exited (0) 1 second ago                       nginx-delete-test
[root@localhost ~]# docker start 3960437b729f
3960437b729f
[root@localhost ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
3960437b729f        nginx               "/docker-entrypoint.…"   25 seconds ago      Up 1 second         80/tcp              nginx-delete-test

1.12 进入容器

1.12.1 使用attach命令

**
不推荐使用该方式进入容器。
因为attach类似于vnc,就算多个人同时进入容器,但是命令行只有一个人能操作。并且一个终端关闭,其他终端也会关闭。
**

不推荐使用该方式

1.12.2 使用exec命令

该方式工作中常用,可以多用户同时使用。
exec: 在运行的容器中执行命令

[root@localhost ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
3960437b729f        nginx               "/docker-entrypoint.…"   9 minutes ago       Up 9 minutes        80/tcp              nginx-delete-test
[root@localhost ~]# docker exec -it 3960437b729f bash
root@3960437b729f:/# ls
bin  boot  dev  docker-entrypoint.d  docker-entrypoint.sh  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@3960437b729f:/# exit
exit

1.12.3 nsenter

nsenter:单纯的进入容器
该命令需要通过PID进入到容器内部,不过可以使用docker inspect获取到容器的PID

[root@localhost ~]# yum install util-linux # nsenter命令在util-linux包中
[root@localhost ~]# docker inspect 3960437b729f|grep State -A 10  # 先找到包含容器PID的字段
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 2296,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2023-03-18T13:25:16.607306011Z",

[root@localhost ~]# docker inspect -f "{{.State.Pid}}" 3960437b729f  # 通过这种方式就可以取出想要的值
2296

[root@localhost ~]# nsenter -t 2296 -m -u -i -n -p  # 进入容器
root@3960437b729f:/# ls
bin  boot  dev  docker-entrypoint.d  docker-entrypoint.sh  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@3960437b729f:/# exit
logout

1.12.3.1 脚本方式

由于单纯使用nsenter太麻烦,所以可以使用脚本

[root@localhost ~]# cat docker-in.sh
#!/bin/bash
docker_in(){
  NAME_ID=$1
  PID=$(docker inspect -f "{{.State.Pid}}" ${NAME_ID})
  nsenter -t ${PID} -m -u -i -n -p
}

docker_in $1

[root@localhost ~]# sh docker-in.sh 3960437b729f
root@3960437b729f:/# exit
logout

1.13 容器的hosts文件

[root@localhost ~]# docker exec -it 3708963039f6 bash
[root@3708963039f6 /]# 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.3      3708963039f6  # 容器默认会将实例ID添加到自己的hosts文件中

[root@3708963039f6 /]# ping 3708963039f6
PING 3708963039f6 (172.17.0.3) 56(84) bytes of data.
64 bytes from 3708963039f6 (172.17.0.3): icmp_seq=1 ttl=64 time=0.031 ms

1.14 容器的批量操作

1.14.1 批量停止正在运行的容器

[root@localhost ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
3708963039f6        eeb6ee3f44bd        "bash"                   4 minutes ago       Up 4 minutes                            C7
3960437b729f        nginx               "/docker-entrypoint.…"   About an hour ago   Up About an hour    80/tcp              nginx-delete-test
[root@localhost ~]# docker ps -q  # -q:只显示容器ID
3708963039f6
3960437b729f
[root@localhost ~]# docker stop `docker ps -q`
3708963039f6
3960437b729f
[root@localhost ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                       PORTS               NAMES
3708963039f6        eeb6ee3f44bd        "bash"                   4 minutes ago       Exited (137) 5 seconds ago                       C7
3960437b729f        nginx               "/docker-entrypoint.…"   About an hour ago   Exited (0) 15 seconds ago                        nginx-delete-test

1.14.2 批量强制停止正在运行的容器

docker kill。
不推荐该方式,可能会丢数据或者造成服务异常,除非容器真的关不掉。

[root@localhost ~]# docker start `docker ps -qa`
3708963039f6
3960437b729f
[root@localhost ~]# docker kill `docker ps -q`
3708963039f6
3960437b729f
[root@localhost ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                       PORTS               NAMES
3708963039f6        eeb6ee3f44bd        "bash"                   7 minutes ago       Exited (137) 4 seconds ago                       C7
3960437b729f        nginx               "/docker-entrypoint.…"   About an hour ago   Exited (137) 4 seconds ago                       nginx-delete-test
[root@localhost ~]#

1.14.3 批量删除已经退出运行的容器

[root@localhost ~]# docker rm `docker ps -aq -f status=exited`
3708963039f6
3960437b729f

[root@localhost ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

1.14.4 批量删除所有容器

危险,会删除正在运行和退出运行的容器

[root@localhost ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
0c3690a93a54        eeb6ee3f44bd        "bash"                   18 seconds ago      Up 17 seconds                           unruffled_thompson
0708d3234dd8        nginx               "/docker-entrypoint.…"   34 seconds ago      Up 33 seconds       80/tcp              laughing_euclid
[root@localhost ~]# docker rm -f `docker ps -qa`
0c3690a93a54
0708d3234dd8
[root@localhost ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

1.15 指定容器DNS

容器默认情况下是使用宿主机的DNS的,当我们需要容器访问内部DNS时,可以手动修改这个DNS地址。

[root@localhost ~]# cat /etc/resolv.conf  # 查看宿主机DNS
# Generated by NetworkManager
nameserver 114.114.114.114
[root@localhost ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
70d121296729        eeb6ee3f44bd        "bash"              7 seconds ago       Up 7 seconds                            bold_hopper
[root@localhost ~]# docker exec -it 70d121296729 cat /etc/resolv.conf  # 查看容器DNS
# Generated by NetworkManager
nameserver 114.114.114.114

1.15.1 方法1:修改宿主机DNS

[root@localhost ~]# vim /etc/resolv.conf  # 给宿主机添加DNS
# Generated by NetworkManager
nameserver 114.114.114.114
nameserver 8.8.8.8
[root@localhost ~]# docker run -it eeb6ee3f44bd bash
[root@24eb3ea96a63 /]# cat /etc/resolv.conf # 查看容器dns
# Generated by NetworkManager
nameserver 114.114.114.114
nameserver 8.8.8.8

1.15.2 方法2:使用–dns参数指定dns地址

[root@localhost ~]# docker run -it --dns 1.1.1.1 eeb6ee3f44bd bash
[root@2b6bf420b08d /]# cat /etc/resolv.conf
nameserver 1.1.1.1
[root@2b6bf420b08d /]# exit
exit

1.16 文件复制

# 复制容器中的文件到宿主机
docker cp 容器ID或容器名:/绝对路径/文件名 宿主机绝对路径

# 复制宿主机中的文件到容器
docker cp 宿主机绝对路径/文件名 容器ID或容器名:/绝对路径/文件名 # 会直接覆盖容器中的源文件

1.17 容器环境变量

有些容器的启动,是需要传递相关的环境变量,才能正常启动的,如下

[root@test01 ~]# docker run -itd --name mysql-5.6 -p 3307:3306 dd3b2a5dcb48
b454e438b22b29342f7a034b9f181cf9e31fd8c7f3ab5b375d696cdaed9c19bd
[root@test01 ~]# docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                    PORTS               NAMES
b454e438b22b        dd3b2a5dcb48        "docker-entrypoint.s…"   3 seconds ago       Exited (1) 1 second ago                       mysql-5.6
[root@test01 ~]# docker logs b454e438b22b  # 上面启动一个mysql容器,但是起来就退出了,查看日志发现需要传递变量才可以
2023-03-20 02:24:37+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.6.51-1debian9 started.
2023-03-20 02:24:37+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2023-03-20 02:24:37+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.6.51-1debian9 started.
2023-03-20 02:24:37+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified
    You need to specify one of the following:
    - MYSQL_ROOT_PASSWORD
    - MYSQL_ALLOW_EMPTY_PASSWORD
    - MYSQL_RANDOM_ROOT_PASSWORD

[root@test01 ~]# docker run -itd --name mysql-5.6 -p 3307:3306 -e MYSQL_ROOT_PASSWORD='123456' dd3b2a5dcb48
3ebe2131b0217e960c1a4d678dc62f54162dd8a5657ea93e1aba316fb52a5538
[root@test01 ~]# docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
3ebe2131b021        dd3b2a5dcb48        "docker-entrypoint.s…"   2 seconds ago       Up 2 seconds        0.0.0.0:3307->3306/tcp   mysql-5.6

1.18 其他命令

1.18.1 更新容器资源配置信息

docker update 容器--cpus 2 # 更新容器的cpu资源配置

1.18.2 获取dockerd的实时事件

docker events  # 容器的增删改查都会记录下来

1.18.3 显示容器的退出状态码

docker wait f8ae0c8dcaf8 #显示容器的退出状态码

2. Docekr镜像与制作

Docker镜像有没有内核吗?

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

在这里插入图片描述
为什么没有内核?

由于容器启动和运行过程中是直接使用了宿主机的内核,所以没有直接调用过物理硬件,所以也不会涉及到硬件驱动,因此也用不上内核和驱动,另外有内核的那是虚拟机。

2.1 制作镜像的方式

(1)docker commit # 基于运行中的容器制作一个新的镜像
(2)dockerfile

2.2 基于docker commit方式制作镜像

相关参数

-a :提交的镜像作者;
-c :使用Dockerfile指令来创建镜像;
-m :提交时的说明文字;
-p :在commit时,将容器暂停(默认参数,不加也会暂停,防止新数据写入)。

2.2.1 下载基础镜像并初始化环境

[root@test01 ~]# docker images |grep centos
centos              centos7.9.2009      eeb6ee3f44bd        18 months ago       204MB
[root@test01 ~]# docker run -it eeb6ee3f44bd bash
[root@97d32845846e /]# yum -y install wget
[root@97d32845846e /]# cd /etc/yum.repos.d/
[root@97d32845846e yum.repos.d]# ls
CentOS-Base.repo  CentOS-Debuginfo.repo  CentOS-Sources.repo  CentOS-fasttrack.repo
CentOS-CR.repo    CentOS-Media.repo      CentOS-Vault.repo    CentOS-x86_64-kernel.repo
[root@97d32845846e yum.repos.d]# rm -f *
[root@97d32845846e yum.repos.d]# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
[root@97d32845846e yum.repos.d]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
[root@97d32845846e yum.repos.d]# ll
total 8
-rw-r--r-- 1 root root 2523 Aug  4  2022 CentOS-Base.repo
-rw-r--r-- 1 root root  664 Aug  4  2022 epel.repo

2.2.2 yum安装并配置nginx

[root@97d32845846e ~]# yum -y install nginx
[root@97d32845846e ~]# yum -y install vim pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop  # 安装常用命令

2.2.3 关闭nginx后台运行

注意Nginx默认是后台运行的,但Docker需要其在前台运行,否则直接退出容器。配置文件中添加daemon off;关闭后台运行。另外可以通过Dockerfile配置CMD命令实现。

[root@97d32845846e ~]# cat /etc/nginx/nginx.conf
# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
daemon off;  # 添加这一行

……省略 部分内容

2.2.4 自定义web页面

[root@97d32845846e ~]# cd /usr/share/nginx/
[root@97d32845846e nginx]# echo 'Docker Yum Nginx' > /usr/share/nginx/index.html
[root@97d32845846e nginx]# mv index.html html/
[root@97d32845846e nginx]# cd html/
[root@97d32845846e html]# cat index.html
Docker Yum Nginx

2.2.5 提交为镜像

[root@test01 ~]# docker commit 97d32845846e centos-nginx:v1
sha256:dc087527a3af62d4e1f0fe7db3200753cc1181c5ffb083476666cef99c95f371
[root@test01 ~]# docker images |grep centos-nginx
centos-nginx        v1                  dc087527a3af        10 seconds ago      546MB

2.2.6 基于刚打的镜像启动一个容器

[root@test01 ~]# docker images |grep centos-nginx
centos-nginx        v1                  dc087527a3af        10 seconds ago      546MB
[root@test01 ~]# docker run -d -p 88:80 --name my-centos-nginx dc087527a3af /usr/sbin/nginx
1193b5c9e5ed217687589b83b0be17da4cb697a3f22cc0ee9017cf23143e9e1a
[root@test01 ~]# docker ps -l
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                NAMES
1193b5c9e5ed        dc087527a3af        "/usr/sbin/nginx"   3 seconds ago       Up 2 seconds        0.0.0.0:88->80/tcp   my-centos-nginx

2.2.7 访问测试

在这里插入图片描述

2.3 基于dockerfile制作编译版nginx 1.16.1镜像

Dockerfile官方文档:https://docs.docker.com/engine/reference/builder/

DockerFile可以说是一种可以被Docker程序解释的脚本,DockerFile是由一条条的命令组成的,每条命令对应linux下面的一条命令,Docker程序将这些DockerFile指令再翻译成真正的linux命令,其有自己的书写方式和支持的命令,Docker程序读取DockerFile 并根据指令生成Docker镜像,相比手动制作镜像的方式,DockerFile更能直观的展示镜像是怎么产生的,有了写好的各种各样DockerFile文件,当后期某个镜像有额外的需求时,只要在之前的DockerFile添加或者修改相应的操作即可重新生成新的Docke镜像,避免了重复手动制作镜像的麻烦,具体如下:
官方文档:https://docs.docker.com/engine/reference/builder/
FROM #在整个dockfile文件中,除了注释之外的第一行,要是from,用于指定父镜像
ADD #用于添加宿主机本地的文件、目录、压缩等资源到镜像里面去,会自动解压tar.gz格式的压缩包,但是无法自动解压zip包(因为tar命令自带的,zip需要额外安装)。
COPY #用于添加宿主机本地的文件、目录、压缩等资源到镜像里面去。
ENV # 设置整个容器的环境变量
EXPOSE # “声明” 映射哪些端口到宿主机上(只是声明,我当它为一个注释说明)
RUN # 执行shell命令,但是一定得是非交互式的方式来执行shell命令
LABEL # 设置镜像的属性标签(如作者信息)
MAINTAINER # 设置镜像的属性标签(该方式可能废弃,推荐使用LABEL)
USER # 指定容器运行中使用的用户(不指定的话就会使用父镜像的默认用户)
VOLUME # 声明一个具有指定名称的挂载点(容器中不存在会自动创建),run的时候没有-v的话,会自动在宿主机的目录下生成一个匿名数据卷。注意,如果任何构建步骤在声明卷后更改了卷中的数据,那么这些更改将被丢弃。(就是被VOLUME声明的目录,后续就不能修改了,就算有修改的步骤,在dockerfile中也不会被执行)
WORKDIR # 定义进入容器时的工作目录
CMD # 启动容器时使用的默认命令或脚本(可以被传参覆盖)
ENTRYPOINT # 启动容器时使用的默认命令或脚本,结合CMD使用时,CMD设置的值会变成ENTRYPOINT的参数

2.3.1 下载镜像并初始化系统

[root@test01 ~]# docker pull centos:centos7.9.2009
[root@test01 ~]# docker run -itd --name my-centos  centos:centos7.9.2009 bash
ea363d152b2dcc6d1755b4c1d28f79bf740e7959bf3043404dd6632210129141
[root@test01 ~]# docker ps -l
CONTAINER ID        IMAGE                   COMMAND             CREATED             STATUS              PORTS               NAMES
ea363d152b2d        centos:centos7.9.2009   "bash"              4 seconds ago       Up 3 seconds                            my-centos

[root@test01 ~]# cd /opt/
[root@test01 opt]# mkdir -p  dockerfile/{web/{nginx,tomcat,jdk,apache},system/{centos,ubuntu,redhat}} #目录结构按照业务类型或系统类型等方式划分,方便后期镜像比较多的时候进行分类。
[root@test01 opt]# cd dockerfile/
[root@test01 dockerfile]# tree
.
├── system
│   ├── centos
│   ├── redhat
│   └── ubuntu
└── web
    ├── apache
    ├── jdk
    ├── nginx
    └── tomcat
  
[root@test01 ~]# cd /opt/dockerfile/web/nginx/
[root@test01 nginx]# mkdir all-in-one
[root@test01 nginx]# cd all-in-one
[root@test01 all-in-one]#

2.3.2 编写Dockerfile

docker build的过程中,会启动一个临时容器,来根据dockerfile中的内容执行操作,执行完后,把该容器提交成为一个镜像。

[root@test01 all-in-one]# cat Dockerfile
#base image
FROM centos:centos7.9.2009

LABEL maintainer="xts 1184964356@qq.com" # 作者信息,可写可不写

RUN yum -y install epel-release && yum -y install vim wget tree lrzsz gcc gcC-C++ automake pcrepcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop

# 测试
[root@test01 all-in-one]# docker build -t nginx-web-v1:1.16.1 . # -t:设置镜像的名称和标签
[root@test01 ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx-web-v1        1.16.1              3f8b5422b301        3 minutes ago       595MB
[root@test01 ~]# docker history nginx-web-v1:1.16.1
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
3f8b5422b301        9 minutes ago       /bin/sh -c yum -y install epel-release && yu…   391MB
4e2685c70d97        12 minutes ago      /bin/sh -c #(nop)  LABEL maintainer=xts 1184…   0B
eeb6ee3f44bd        18 months ago       /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>           18 months ago       /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B
<missing>           18 months ago       /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4…   204MB

# 下载nginx源码包
[root@test01 all-in-one]# wget http://nginx.org/download/nginx-1.16.1.tar.gz

# 继续编写dockerfile
[root@test01 all-in-one]# tail -1 Dockerfile
ADD nginx-1.16.1.tar.gz /usr/local/src/  # 再次构建的时候,docker会检测到上面是已经执行过的,就直接从add开始执行了

# 再测试构建
[root@test01 all-in-one]# docker build -t nginx-web-v2:1.16.1 .
Sending build context to Docker daemon  1.077MB
……省略部分输出
Successfully built cba4b82c48bf
Successfully tagged nginx-web-v2:1.16.1

[root@test01 ~]# docker run -it --rm nginx-web-v2:1.16.1 bash
[root@58823fe3b73f /]# ll /usr/local/src/
total 1012
-rw-r--r-- 1 root root 1032630 Aug 13  2019 nginx-1.16.1  # 这里可以看到tar包已经被ADD解压了
[root@58823fe3b73f /]# exit
exit

# 继续编写dockerfile
[root@test01 all-in-one]# tail -1 Dockerfile
RUN cd /usr/local/src/nginx-1.16.1 && ./configure --prefix=/apps/nginx --with-http_sub_module && make && make install

# 再次构建
[root@test01 all-in-one]# docker build -t nginx-web-v3:1.16.1 .

# 测试
[root@test01 all-in-one]# docker run -it --rm nginx-web-v3:1.16.1 bash
[root@d0acc899d983 /]# cd apps/
[root@d0acc899d983 apps]# ls
nginx
[root@d0acc899d983 apps]# cd nginx/
[root@d0acc899d983 nginx]# ls
conf  html  logs  sbin
[root@d0acc899d983 nginx]# ./sbin/nginx
[root@d0acc899d983 nginx]# ss -lntup |grep 80
tcp    LISTEN     0      128       *:80                    *:*                   users:(("nginx",pid=19,fd=6

# 新开一个窗口
[root@test01 ~]# curl -I localhost:8088
HTTP/1.1 200 OK
Server: nginx/1.16.1
Date: Tue, 21 Mar 2023 07:04:16 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 21 Mar 2023 03:25:25 GMT
Connection: keep-alive
ETag: "641923a5-264"
Accept-Ranges: bytes

# 自定义nginx配置文件
[root@test01 all-in-one]# docker  run -itd nginx-web-v3:1.16.1 bash
7ced74ca645095596958f71dfaceb06e23922c9ded6ce112c54657cfbbf91c85
[root@test01 all-in-one]# docker ps -l
CONTAINER ID        IMAGE                 COMMAND             CREATED             STATUS              PORTS               NAMES
7ced74ca6450        nginx-web-v3:1.16.1   "bash"              2 seconds ago       Up 2 seconds                            quizzical_hopper
[root@test01 all-in-one]# docker cp 7ced74ca6450:/apps/nginx/conf/nginx.conf ./nginx.conf
[root@test01 all-in-one]# docker cp 7ced74ca6450:/apps/nginx/html/index.html ./index.html
[root@test01 all-in-one]# ll -rt
total 1064
-rw-r--r-- 1 root root 1032630 Aug 14  2019 nginx-1.16.1.tar.gz
-rw------- 1 root root   40920 Mar 20 17:57 nohup.out
-rw-r--r-- 1 root root     411 Mar 21 16:24 Dockerfile
-rw-r--r-- 1 root root    2656 Mar 21 16:25 nginx.conf
-rw-r--r-- 1 root root     612 Mar 21 16:25 index.html

# 自定义配置文件和html文件
[root@test01 all-in-one]# cat nginx.conf
user  nginx;  # 修改
worker_processes  auto; # 修改

        location / {
            root   /data/nginx/html;  # 修改
            index  index.html index.htm;
        }

# 生成测试页面
[root@test01 all-in-one]# echo 'Docker Nginx Test' > index.html

# 编辑dockerfile
[root@test01 all-in-one]# tail -4 Dockerfile
RUN useradd nginx  # 创建nginx所需用户

ADD nginx.conf /apps/nginx/conf/nginx.conf  # 复制宿主机上修改过的nginx配置文件到容器中,文件名可以不指定,会直接覆盖源文件
ADD index.html /data/nginx/html/  # 复制宿主机上的html文件到容器中,注意html/ 这里一定要写/,不然add index.html会把html目录替换成一个文件

# 构建镜像
[root@test01 all-in-one]# docker build -t nginx-web-v4:1.16.1 .
[root@test01 ~]# docker images |grep v4
nginx-web-v4        1.16.1              67ce34721588        56 seconds ago      618M

# 启动容器
[root@test01 all-in-one]# docker run -it --rm -p 8088:80 nginx-web-v4:1.16.1
[root@ab57914facd8 /]# id nginx
uid=1000(nginx) gid=1000(nginx) groups=1000(nginx)
[root@ab57914facd8 /]# tree /data
/data
`-- nginx
    `-- html
        `-- index.html

2 directories, 1 file
[root@ab57914facd8 /]# /apps/nginx/sbin/nginx

# 再开一个窗口访问测试
[root@test01 all-in-one]# curl localhost:8088
Docker Nginx Test

# 再次编辑dockerfile
[root@test01 all-in-one]# tail -5 Dockerfile
EXPOSE 80 443  # 声明端口

CMD /apps/nginx/sbin/nginx;tail -f /etc/hosts # 先让nginx启动,然后使用tail命令,使得有进程是前台运行的,这样容器就不会退出

# 构建镜像
[root@test01 all-in-one]# docker build -t nginx-web-v4:1.16.1 .

# 启动测试
[root@test01 all-in-one]# docker run -d -p 8088:80 nginx-web-v4:1.16.1
a59034b756aa2a307732f7f177ad4b15fe6263e1d21d9d3ca72ffda447affc9c
[root@test01 all-in-one]# docker ps -l
CONTAINER ID        IMAGE                 COMMAND                CREATED             STATUS              PORTS                           NAMES
a59034b756aa        nginx-web-v4:1.16.1   "tail -f /etc/hosts"   5 seconds ago       Up 4 seconds        443/tcp, 0.0.0.0:8088->80/tcp   recursing_aryabhata

[root@test01 all-in-one]# docker exec -it 8409b9b27a64 bash
[root@8409b9b27a64 /]# ps -ef 
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 10:01 pts/0    00:00:00 /bin/sh -c /apps/nginx/sbin/nginx;tail -f /etc/hosts  # 初始化的进程
root         7     1  0 10:01 ?        00:00:00 nginx: master process /apps/nginx/sbin/nginx
nginx        8     7  0 10:01 ?        00:00:00 nginx: worker process
root         9     1  0 10:01 pts/0    00:00:00 tail -f /etc/hosts
nginx       10     7  0 10:01 ?        00:00:00 nginx: worker process
root        11     0  1 10:02 pts/1    00:00:00 bash
root        26    11  0 10:02 pts/1    00:00:00 ps -ef

[root@test01 ~]# curl localhost:8088
Docker Nginx Test

# 编辑dockerfile,使用nginx进程命令前台运行
[root@test01 all-in-one]# tail -1 Dockerfile
CMD ["/apps/nginx/sbin/nginx","-g","daemon off;"]

# 构建
[root@test01 all-in-one]# docker build -t nginx-web-v4:1.16.1 .

# 运行
[root@test01 all-in-one]# docker run -d -p 8088:80 nginx-web-v4:1.16.1
752d327d2e2dc9bdcc634aeeb40c588368ccb8e484de6ac0aaf716c00bbe9718
[root@test01 all-in-one]# docker ps -l
CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                           NAMES
752d327d2e2d        nginx-web-v4:1.16.1   "/apps/nginx/sbin/ng…"   2 seconds ago       Up 2 seconds        443/tcp, 0.0.0.0:8088->80/tcp   cranky_mccarthy
[root@test01 all-in-one]# docker exec -it 752d327d2e2d bash
[root@752d327d2e2d /]# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 10:08 ?        00:00:00 nginx: master process /apps/nginx/sbin/nginx -g daemon off;  # 初始化进程
nginx        6     1  0 10:08 ?        00:00:00 nginx: worker process
nginx        7     1  0 10:08 ?        00:00:00 nginx: worker process
root         8     0  1 10:10 pts/0    00:00:00 bash
root        23     8  0 10:10 pts/0    00:00:00 ps -ef

# 测试
[root@test01 all-in-one]# curl localhost:8088
Docker Nginx Test

# 最终dockerfile
[root@test01 all-in-one]# cat Dockerfile 
#base image
FROM centos:centos7.9.2009 

LABEL maintainer="xts 1184964356@qq.com"

RUN yum -y install epel-release && yum -y install vim wget tree lrzsz gcc gcC-C++ automake pcrepcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop

ADD nginx-1.16.1.tar.gz /usr/local/src/

RUN cd /usr/local/src/nginx-1.16.1 && ./configure --prefix=/apps/nginx --with-http_sub_module && make && make install
RUN useradd nginx

ADD nginx.conf /apps/nginx/conf/nginx.conf
ADD index.html /data/nginx/html/

EXPOSE 80 443

#CMD /apps/nginx/sbin/nginx;tail -f /etc/hosts
CMD ["/apps/nginx/sbin/nginx","-g","daemon off;"]  # 注意:这里的daemon off可以直接加到nginx.conf中,CMD这就变成CMD ["/apps/nginx/sbin/nginx"] 

# 使用脚本的方式来启动
## 使用脚本 很多地方可以自己控制
[root@test01 all-in-one]# cat run_nginx.sh 
#!/bin/bash
/apps/nginx/sbin/nginx -g "daemon off;" # 在启动之前 可以定义很多其他需要的操作

# 编辑dockerfile
[root@test01 all-in-one]# cat Dockerfile
#base image
FROM centos:centos7.9.2009 

LABEL maintainer="xts 1184964356@qq.com"

RUN yum -y install epel-release && yum -y install vim wget tree lrzsz gcc gcC-C++ automake pcrepcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop

ADD nginx-1.16.1.tar.gz /usr/local/src/

RUN cd /usr/local/src/nginx-1.16.1 && ./configure --prefix=/apps/nginx --with-http_sub_module && make && make install
RUN useradd nginx

ADD nginx.conf /apps/nginx/conf/nginx.conf
ADD index.html /data/nginx/html/
ADD run_nginx.sh /apps/nginx/sbin/run_nginx.sh # 修改部分
RUN chmod +x /apps/nginx/sbin/run_nginx.sh # 修改部分

EXPOSE 80 443

CMD ["run_nginx.sh"] # 修改部分

# 构建并运行
[root@test01 all-in-one]# docker build -t nginx-web-v4:1.16.1 .
[root@test01 all-in-one]# docker  run -d -p 8088:80 nginx-web-v4:1.16.1
[root@test01 all-in-one]# curl localhost:8088
Docker Nginx Test

2.4 容器运行注意事项

2.4.1 关于容器运行的

运行容器的时候,一定是要有一个进程在容器tty终端前台运行的。
方式:
(1)命令方式
tail -f /etc/hosts # 这种方式可以一直在前台运行


(2)服务进程
如nginx配置中,关闭默认的后台运行,使其前台运行,daemon off;


(3)脚本
通过编写脚本,让进程前台运行

2.4.2 关于CMD的

CMD有两种用法:
用法1:CMD 命令1;命令2;命令N # 这种不加[ ],适合多条命令在一个CMD中执行


用法2:CMD [“命令”, “参数1”, “参数2”] # 这种用法会将 command 和其后面的参数视为一个数组,它不会使用 shell 命令解析器,而是直接执行,更加安全和高效。

3. 镜像分层构建

在这里插入图片描述

3.1 自定义Tomcat业务镜像

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

3.1.1 使用CentOS基础镜像

3.1.1.1 配置基础镜像与基本环境
[root@test01 ~]# cd /opt/dockerfile/system/centos/
[root@test01 centos]# docker images |grep centos
centos-nginx        v1                  dc087527a3af        45 hours ago        546MB
centos              centos7.9.2009      eeb6ee3f44bd        18 months ago       204MB

[root@test01 centos]# cat Dockerfile 
# 第一层
FROM centos:centos7.9.2009

LABEL maintainer="xts 1184964356@qq.com"

# 第二层
RUN rm -fr /etc/yum.repos.d/* && curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo && \
yum clean all && yum makecache && curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo && yum clean all && yum makecache && \
yum -y install vim wget tree lrzsz gcc gcC-C++ automake pcrepcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop && groupadd www -g 2023 && useradd www -u 2023 -g www

# 准备构建镜像相关的脚本
[root@test01 centos]# cat build-command.sh
#!/bin/bash
docker build -t centos-base:7.9.2009 .

# 执行脚本 构建镜像
[root@test01 centos]# sh build-command.sh
[root@test01 centos]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos-base         7.9.2009            dd4f9e4b93a0        26 minutes ago      949MB
3.1.1.2 构建jdk镜像
[root@test01 dockerfile]# cd web/jdk/
[root@test01 jdk]# ls
[root@test01 jdk]# mkdir jdk-8u361
[root@test01 jdk]# cd jdk-8u361
[root@test01 jdk-8u361]# pwd
/opt/dockerfile/web/jdk/jdk-8u361

# 上传jdk文件
[root@test01 jdk-8u361]# ll -h
total 133M
-rw-r--r-- 1 root root 133M Mar 22 20:26 jdk-8u361-linux-x64.tar.gz

# 复制基础镜像中的profile文件,添加对应环境变量
[root@test01 jdk-8u361]# docker run -dit centos-base:7.9.2009 bash
7ea2cb225a0b791e95881721c9a4bd5d3aeba1ddf74d6075f1f717cf023653ac
[root@test01 jdk-8u361]# docker ps -l
CONTAINER ID        IMAGE                  COMMAND             CREATED             STATUS              PORTS               NAMES
7ea2cb225a0b        centos-base:7.9.2009   "bash"              3 seconds ago       Up 2 seconds                            optimistic_tesl

[root@test01 jdk-8u361]# docker cp 7ea2cb225a0b:/etc/profile ./
[root@test01 jdk-8u361]# ll -rt
total 135520
-rw-r--r-- 1 root root      1819 Apr  1  2020 profile
[root@test01 jdk-8u361]# tail -4 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

# 编辑dockerfile
[root@test01 jdk-8u361]# tail -1 Dockerfile
ADD profile /etc/profile

# 编辑构建脚本进行构建
[root@test01 jdk-8u361]# cat build-command.sh
#!/bin/bash
docker build -t centos-jdk-base:8u361 .

[root@test01 jdk-8u361]# sh build-command.sh
[root@test01 jdk-8u361]# docker images |grep centos-jdk-base
centos-jdk-base     8u361               c6acb95cad1f        30 seconds ago      1.29GB

# 运行容器检查配置
[root@test01 jdk-8u361]# docker run -it --rm centos-jdk-base:8u361 bash
[root@80e83a6cdf48 /]# tail -4 /etc/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

# 注意点
[root@56b659c7d483 /]# java
bash: java: command not found
[root@56b659c7d483 /]# su - www
[www@56b659c7d483 ~]$ java -version
java version "1.8.0_361"
Java(TM) SE Runtime Environment (build 1.8.0_361-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.361-b09, mixed mode)
# 为什么上面java命令root没法使用,www用户确能使用,是因为容器在启动时,root用户不会去读profile文件,除非手动source一下。

# 编辑dockerfile,为root用户添加java环境变量
[root@test01 jdk-8u361]# tail -4 Dockerfile
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

# 构建镜像
[root@test01 jdk-8u361]# sh build-command.sh
[root@test01 jdk-8u361]# docker images 
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos-jdk-base     8u361               765d45445897        13 seconds ago      1.29GB

# 启动容器检查配置
[root@test01 jdk-8u361]# docker run -it --rm centos-jdk-base:8u361 bash
[root@f93ada792cc8 /]# java -version
java version "1.8.0_361"
Java(TM) SE Runtime Environment (build 1.8.0_361-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.361-b09, mixed mode)

# 修改容器时间,同步宿主机时间(这一步可以在构建基础镜像的时候做也行)
[root@0cbdbb93c628 /]# date  #这是修改前的容器时间,需要加8小时才能对应现在的北京时间
Thu Mar 23 03:30:54 UTC 2023

[root@test01 jdk-8u361]# tail -1 Dockerfile
RUN rm -fr /etc/localtime && ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

# 构建镜像 查看时区
[root@test01 jdk-8u361]# !sh
sh build-command.sh

[root@test01 jdk-8u361]# docker run -it --rm centos-jdk-base:8u361 bash
[root@5552b9c8825d /]# date
Thu Mar 23 11:37:51 CST 2023
[root@5552b9c8825d /]# exit
exit

3.1.2 从jdk镜像构建tomcat 8镜像

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

3.1.2.1 下载tomcat包
[root@test01 tomcat]# wget https://archive.apache.org/dist/tomcat/tomcat-8/v8.5.87/bin/apache-tomcat-8.5.87.tar.gz
[root@test01 tomcat]# ll -h
total 11M
-rw------- 1 root root 11M Mar 23 13:42 apache-tomcat-8.5.87.tar.gz
3.1.2.2 编辑dockerfile
[root@test01 tomcat]# cat Dockerfile
# tomcat base image
FROM centos-jdk-base:8u361

LABEL maintainer="xts 1184964356@qq.com"

ADD apache-tomcat-8.5.87.tar.gz /apps

RUN ln -sv /apps/apache-tomcat-8.5.87 /apps/tomcat
3.1.2.3 编写构建脚本
[root@test01 tomcat]# cat build-command.sh 
#!/bin/bash
docker build -t tomcat-centos-base:v8.5.87 .
3.1.2.4 构建镜像,检查配置
[root@test01 tomcat]# sh build-command.sh
[root@test01 tomcat]# docker run -it --rm tomcat-centos-base:v8.5.87 bash
[root@44d9e0653658 /]# ll /apps/
total 0
drwxr-xr-x 9 root root 220 Mar 23 14:39 apache-tomcat-8.5.87
lrwxrwxrwx 1 root root  26 Mar 23 14:37 tomcat -> /apps/apache-tomcat-8.5.87
[root@44d9e0653658 /]# ll /apps/tomcat/
total 128
-rw-r----- 1 root root 19992 Feb 28 03:32 BUILDING.txt
-rw-r----- 1 root root  6210 Feb 28 03:32 CONTRIBUTING.md
-rw-r----- 1 root root 57011 Feb 28 03:32 LICENSE
-rw-r----- 1 root root  1726 Feb 28 03:32 NOTICE
-rw-r----- 1 root root  3398 Feb 28 03:32 README.md
-rw-r----- 1 root root  7139 Feb 28 03:32 RELEASE-NOTES
-rw-r----- 1 root root 16505 Feb 28 03:32 RUNNING.txt
drwxr-x--- 2 root root  4096 Mar 23 14:39 bin
drwx------ 2 root root   238 Mar 23 14:39 conf
drwxr-x--- 2 root root  4096 Mar 23 14:39 lib
drwxr-x--- 2 root root     6 Feb 28 03:32 logs
drwxr-x--- 2 root root    30 Mar 23 14:39 temp
drwxr-x--- 7 root root    81 Mar 23 14:39 webapps
drwxr-x--- 2 root root     6 Feb 28 03:32 work

3.1.3 构建业务镜像一

到业务镜像这一步,就可以把开发给的代码编译后,放到基础镜像中运行了。

[root@test01 tomcat]# mkdir tomcat-base-8.5.87
[root@test01 tomcat]# mv * tomcat-base-8.5.87
mv: cannot move ‘tomcat-base-8.5.87’ to a subdirectory of itself, ‘tomcat-base-8.5.87/tomcat-base-8.5.87’
[root@test01 tomcat]# ll tomcat-base-8.5.87/
total 10408
-rw------- 1 root root 10645961 Feb 28 03:55 apache-tomcat-8.5.87.tar.gz
-rw-r--r-- 1 root root       57 Mar 23 14:02 build-command.sh
-rw-r--r-- 1 root root      200 Mar 23 14:37 Dockerfile
3.1.3.1 按服务名创建目录
[root@test01 tomcat]# mkdir tomcat-app1 tomcat-app2
[root@test01 tomcat]# ll
total 0
drwxr-xr-x 2 root root  6 Mar 23 15:53 tomcat-app1
drwxr-xr-x 2 root root  6 Mar 23 15:53 tomcat-app2
drwxr-xr-x 2 root root 83 Mar 23 15:51 tomcat-base-8.5.87
[root@test01 tomcat]# cd tomcat-app1
[root@test01 tomcat-app1]# 
3.1.3.2 编辑tomcat配置文件
[root@test01 tomcat-app1]# docker run -itd tomcat-centos-base:v8.5.87 bash
080b5669e5e76f519d350a65ec6f52ca71e673b4c63cd2ccb0ef0a385a892091
[root@test01 tomcat-app1]# docker ps -l
CONTAINER ID        IMAGE                        COMMAND             CREATED             STATUS              PORTS               NAMES
080b5669e5e7        tomcat-centos-base:v8.5.87   "bash"              3 seconds ago       Up 1 second                             serene_lalande
[root@test01 tomcat-app1]# docker exec -it 080b5669e5e7 bash
[root@080b5669e5e7 /]# ll /apps/tomcat/conf/server.xml 
-rw------- 1 root root 7580 Feb 28 03:32 /apps/tomcat/conf/server.xml
[root@080b5669e5e7 /]# exit
exit
[root@test01 tomcat-app1]# docker cp  080b5669e5e7:/apps/tomcat/conf/server.xml ./
[root@test01 tomcat-app1]# ll -rt
total 16
-rw------- 1 root root 7580 Feb 28 03:32 server.xml

[root@test01 tomcat-app1]# grep "Host name" server.xml
      <Host name="localhost"  appBase="/data/tomcat/webapps" # 修改appBase为自定义的目录
3.1.3.3 编辑dokerfile
[root@test01 tomcat-app1]# cat Dockerfile
# tomcat app 1 image
FROM tomcat-centos-base:v8.5.87

LABEL maintainer="xts 1184964356@qq.com"

ADD run_tomcat.sh /apps/tomcat/bin/run_tomcat.sh
ADD server.xml /apps/tomcat/conf/server.xml
ADD memtest.war /data/tomcat/webapps

RUN chown -R www.www /data /apps

EXPOSE 8080 8443

CMD ["/apps/tomcat/bin/run_tomcat.sh"]
3.1.3.4 编辑启动脚本
[root@test01 tomcat-app1]# cat run_tomcat.sh
#!/bin/bash
# 下面启动方式二选一
## 启动方式1
su - www -c "/apps/tomcat/bin/catalina.sh run" # 该方式前台运行(普通用户)

## 启动方式2
#su - www -c "/apps/tomcat/bin/catalina.sh start" # 普通用户
#su - www -c "tail -f /etc/hosts"
3.1.3.5 构建镜像并运行
[root@test01 tomcat-app1]# cat build-command.sh
#!/bin/bash
docker build -t tomcat-app1:v1 .

[root@test01 tomcat-app1]# sh build-command.sh
[root@test01 tomcat-app1]# docker images |grep tomcat-app1
tomcat-app1          v1                  417f14852f9a        14 seconds ago      1.31GB

[root@test01 tomcat-app1]# docker run -d -p 8080:8080 tomcat-app1:v1
3.1.3.6 访问测试

在这里插入图片描述

3.1.4 构建业务镜像二

3.1.4.1 准备首页文件
[root@test01 tomcat]# cd tomcat-app2/
[root@test01 tomcat-app2]# ls
[root@test01 tomcat-app2]# mkdir myapp
[root@test01 tomcat-app2]# cd myapp
[root@test01 myapp]# echo '<h1>Docker Test App2</h1>' > index.jsp
[root@test01 myapp]# cat index.jsp
<h1>Docker Test App2</h1>

[root@test01 tomcat-app2]# tar zcvf myapp.tar.gz myapp
myapp/
myapp/index.jsp
3.1.4.2 准备构建脚本
[root@test01 tomcat-app2]# cp ../tomcat-app1/build-command.sh ./
[root@test01 tomcat-app2]# vim build-command.sh 
[root@test01 tomcat-app2]# cat build-command.sh
#!/bin/bash
docker build -t tomcat-app2:v1 .
3.1.4.3 准备dockerfile
[root@test01 tomcat-app2]# cp ../tomcat-app1/Dockerfile ./
[root@test01 tomcat-app2]# vim Dockerfile 
[root@test01 tomcat-app2]# cat Dockerfile
# tomcat app 1 image
FROM tomcat-centos-base:v8.5.87

LABEL maintainer="xts 1184964356@qq.com"

ADD myapp.tar.gz /data/tomcat/webapps/  # 修改的部分
ADD run_tomcat.sh /apps/tomcat/bin/run_tomcat.sh
ADD server.xml /apps/tomcat/conf/server.xml

RUN chown -R www.www /data /apps

EXPOSE 8080 8443

CMD ["/apps/tomcat/bin/run_tomcat.sh"]
3.1.4.4 准备tocmat配置文件和启动脚本
[root@test01 tomcat-app2]# cp ../tomcat-app1/run_tomcat.sh ./
[root@test01 tomcat-app2]# cp ../tomcat-app1/server.xml ./
3.1.4.5 构建镜像并运行
[root@test01 tomcat-app2]# sh build-command.sh
[root@test01 tomcat-app2]# docker run -d -p 8081:8080 tomcat-app2:v1
3.1.4.6 访问测试

在这里插入图片描述

3.2 构建haporxy镜像

下载地址:https://www.haproxy.org/#down

3.2.1 准备dockerfile

[root@test01 ~]# cd /opt/dockerfile/web/
[root@test01 web]# mkdir haporxy
[root@test01 web]# cd haporxy
[root@test01 haporxy]# cat Dockerfile
# haproxy image
FROM centos-base:7.9.2009

RUN yum install -y libtermcap-devel ncurses-devel libevent-devel readline-devel 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 tcpdmp wget ntpdate

3.2.3 准备构建脚本

[root@test01 haporxy]# cat build-command.sh 
#!/bin/bash
docker build -t haproxy:v2.2.11 .

3.2.4 构建测试

[root@test01 haporxy]# sh build-command.sh
……省略部分输出
Successfully built 1524cc97aa69
Successfully tagged haproxy:v2.2.11

3.2.5 编辑dockerfile

[root@test01 haporxy]# tail -3 Dockerfile
ADD haproxy-2.2.11.tar.gz /usr/local/src/

RUN cd /usr/local/src/haproxy-2.2.11 && make ARCH=x86_64 TARGET=linux-glibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_CPU_AFFINITY=1 PREFIX=/apps/haproxy && make install PREFIX=/apps/haproxy && cp haproxy /usr/sbin/ && mkdir /apps/haproxy/run

3.2.6 构建测试

[root@test01 haporxy]# sh build-command.sh
……省略部分输出
Successfully built 421003565e9f
Successfully tagged haproxy:v2.2.11

3.2.7 运行容器检查配置

[root@test01 haporxy]# docker run -it --rm haproxy:v2.2.11 bash
[root@1bc902da71aa /]# ll /apps/
total 0
drwxr-xr-x 5 root root 42 Mar 24 06:14 haproxy
[root@1bc902da71aa /]# ll /apps/haproxy/
total 0
drwxr-xr-x 3 root root 21 Mar 24 06:14 doc
drwxr-xr-x 2 root root 21 Mar 24 06:14 sbin
drwxr-xr-x 3 root root 17 Mar 24 06:14 share
[root@1bc902da71aa /]# /apps/haproxy/sbin/haproxy -v
HA-Proxy version 2.2.11-c58c4e4 2021/03/18 - https://haproxy.org/
Status: long-term supported branch - will stop receiving fixes around Q2 2025.
Known bugs: http://www.haproxy.org/bugs/bugs-2.2.11.html
Running on: Linux 3.10.0-1062.el7.x86_64 #1 SMP Wed Aug 7 18:08:02 UTC 2019 x86_64
[root@1bc902da71aa /]# exit
exit

3.2.8 编辑服务启动脚本

[root@test01 haporxy]# cat run_haproxy.sh
#!/bin/bash
/apps/haproxy/sbin/haproxy -f /etc/haproxy/haproxy.cfg
tail -f /etc/hosts

3.2.9 准备haproxy配置文件

[root@test01 haporxy]# cat haproxy.cfg
[root@test01 haporxy]# cat haproxy.cfg
global
  chroot /apps/haproxy
  uid 99
  gid 99
  daemon
  nbproc 1
  pidfile /apps/haproxy/run/haproxy.pid
  log 127.0.0.1 local3 info

defaults
  option http-keep-alive
  option forwardfor
  mode http
  timeout connect 300000ms
  timeout client 300000ms
  timeout server 300000ms

listen stats
  mode http
  bind 0.0.0.0:9999
  stats enable
  log global
  stats uri /haproxy-status
  stats auth haadmin:123456
 
listen web_port
  bind 0.0.0.0:80
  mode http
  log global
  balance roundrobin
  server app1 172.17.0.2:8080 check inter 3000 fall 2 rise 5  # 业务容器1(因为默认情况下,容器之间是可以通讯的,所以可以直接写容器IP和端口)
  server app2 172.17.0.3:8080 check inter 3000 fall 2 rise 5  # 业务容器2(因为默认情况下,容器之间是可以通讯的,所以可以直接写容器IP和端口)

3.2.10 编辑dockerfile

[root@test01 haporxy]# chmod +x run_haproxy.sh

[root@test01 haporxy]# tail -4 Dockerfile
ADD run_haproxy.sh /apps/haproxy/bin/run_haproxy.sh
ADD haproxy.cfg /etc/haproxy/haproxy.cfg

CMD ["/apps/haproxy/bin/run_haproxy.sh"]

3.2.11 构建镜像

[root@test01 haporxy]# sh build-command.sh
…………省略部分输出
Successfully built cb9bcb3e5858
Successfully tagged haproxy:v2.2.11

3.2.12 启动检查

[root@test01 haporxy]# docker run -d -p 80:80 -p 9999:9999 haproxy:v2.2.11
d70fd3b35e4271fc0d56e960fa7d2a8d6bc065732c07164be03b59c694ba0052
[root@test01 haporxy]# docker exec -it d70fd3b35e4271fc0d56e960fa7d2a8d6bc065732c07164be03b59c694ba0052 bash
[root@d70fd3b35e42 /]# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 17:59 ?        00:00:00 /bin/bash /apps/haproxy/bin/run_haproxy.sh
nobody       8     1  0 17:59 ?        00:00:00 /apps/haproxy/sbin/haproxy -f /etc/haproxy/haproxy.cfg # haproxy启动进程
root         9     1  0 17:59 ?        00:00:00 tail -f /etc/hosts
root        11     0  0 17:59 pts/0    00:00:00 bash
root        26    11  0 17:59 pts/0    00:00:00 ps -ef
[root@d70fd3b35e42 /]# netstat -lntup
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:9999            0.0.0.0:*               LISTEN      -                  # 监听端口 
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -                  # 监听端口 
udp        0      0 0.0.0.0:52349           0.0.0.0:*                           -                   
udp        0      0 0.0.0.0:60988           0.0.0.0:*                           -   

3.2.13 访问测试

访问status页面
在这里插入图片描述
随机访问一个页面
在这里插入图片描述

3.3 镜像分层原理之共享镜像层(Dockerfile缓存)

在这里插入图片描述

如上图,所有镜像大小加起来已经好几G了,为什么overlay2目录才2.5G,这就是我们要说的共享镜像层。
我们在拉取镜像的时候,经常会看到 Already exists,这是说明拉取的这个镜像中,该层在宿主机上已经存在了。
比如:有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像(因为镜像的ID唯一);同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。

在这里插入图片描述

如上图,两个容器镜像大小加起来1000M,但是宿主机上实际只会占用700M的存储空间。
因为两个镜像的相同部分是可以共享使用的,也就是dockerfile缓存。

3.4 本章重点总结

3.4.1 必须掌握

(1)熟练掌握dockerfile的指令使用
(2)熟练通过dockerfile制作镜像的各种方式(yum安装、编译安装)
(3)镜像的分层构建
(4)CMD和ENTRYPOINT的区别及使用

3.4.2 扩展

构建haproxy+nginx+tomcat的小型站点的全部镜像,实现动静分离。

4. 总结

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值