一、Docker镜像的说明

1、Docker镜像中没有内核

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


2、为什么没有内核

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


3、容器中的程序的运行

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


4、制作镜像的方法

Docker 镜像制作类似于虚拟机的镜像(模版)制作,相关配置等基础环境配置完成,然后将其做成镜像,最后再批量从镜像批量生成容器实例,这样可以极大 的简化相同环境的部署工作。

Docker的镜像制作分为手动制作(基于容器)和自动制作(基于DockerFile)。

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


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

1、基于容器手动制作镜像的步骤

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

-a          #提交的镜像作者
-c          #使用Dockerfile指令来创建镜像
-m          #提交时的说明文字
-p          #在commit时,将容器暂停
1.下载一个系统的官方基础镜像,如: CentOS 或 Ubuntu  

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

3.在容器里面做配置操作、安装基础命令、配置运行环境、安装服务和配置服务、放业务程序代码 

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

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

2、基于centos编译制作nginx镜像

[root@c7-docker-node1-71 ~]# docker run -it -d --name centos_nginx_node1_os centos
c556b961f07fe8ad21e532e52a83ab2f9cd1427897cf25a53e0d6147cb9dcc04
[root@c7-docker-node1-71 ~]# docker exec -it centos_nginx_node1_os bash

[root@c556b961f07f ~]# yum -y install gcc pcre-devel openssl-devel zlib-devel wget make
[root@c556b961f07f ~]# useradd -s /sbin/nologin nginx
[root@c556b961f07f ~]# cd /usr/local/src/
[root@c556b961f07f src]# wget https://nginx.org/download/nginx-1.22.1.tar.gz
[root@c556b961f07f src]# tar xf nginx-1.22.1.tar.gz 
[root@c556b961f07f src]# cd nginx-1.22.1
[root@c556b961f07f nginx-1.22.1]# ./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module
[root@c556b961f07f nginx-1.22.1]# make && make install

[root@c556b961f07f nginx-1.22.1]# chown -R nginx:nginx /apps/nginx
[root@c556b961f07f nginx-1.22.1]# ln -s /apps/nginx/sbin/nginx /usr/sbin/
[root@c556b961f07f nginx-1.22.1]# nginx -v
nginx version: nginx/1.22.1

[root@c556b961f07f nginx-1.22.1]# mkdir /apps/nginx/run

[root@c556b961f07f nginx-1.22.1]# vi /apps/nginx/conf/nginx.conf

[root@c556b961f07f nginx-1.22.1]# head -n 10 /apps/nginx/conf/nginx.conf

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

pid        /apps/nginx/run/nginx.pid;
daemon off;

[root@c556b961f07f nginx-1.22.1]# nginx -c ./conf/nginx.conf 

[root@c7-docker-node1-71 ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
c556b961f07f        centos              "/bin/bash"         23 minutes ago      Up 23 minutes                           centos_nginx_node1_os

[root@c7-docker-node1-71 ~]# docker commit -a "jiutingqiu@www.elysia.com" -c 'CMD /sbin/nginx -c /apps/nginx/conf/nginx.conf' -c "EXPOSE 80" centos_nginx_node1_os cnno:v1.0
sha256:a5647c8ab88f4921ecead6760c6ce3ca3494b3ed2ae7f5fa2d61adc9339997d4

[root@c7-docker-node1-71 ~]# docker images 
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
cnno                v1.0                a5647c8ab88f        19 seconds ago      473MB

1.测试

[root@c7-docker-node1-71 ~]# docker run -it -p 80:80 -d cnno:v1.0
f04d571d898611a363f3035ce9bf263060f34685449bbfdeec9375f52adceb1d
[root@c7-docker-node1-71 ~]# curl 127.0.0.1:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

2.错误

Error: Failed to download metadata for repo 'appstream': Cannot prepare internal mirrorlist: No URLs in mirrorlist

[root@c556b961f07f /]# cd /etc/yum.repos.d/
[root@c556b961f07f yum.repos.d]# sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*

[root@c556b961f07f yum.repos.d]# sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*


三、利用 DockerFile 文件执行 docker build 自动构建镜像

1、Dockerfile使用详解

1.Dockerfile 介绍

DockerFile 是一种被Docker程序解释执行的脚本,由一条条的命令组成的,每条命令对应linux下面的 一条命令,Docker程序将这些DockerFile指令再翻译成真正的linux命令,其有自己的书写方式和支持的 命令,Docker程序读取DockerFile并根据指令生成Docker镜像。


2.Dockerfile 文件格式

Dockerfile 是一个有特定语法格式的文本文件

Dockerfile 文件说明

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

使用 # 开始作为注释

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

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

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

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

3.Dockerfile 相关指令

ADD
COPY
ENV
EXPOSE
FROM
LABEL
STOPSIGNAL
USER
VOLUME
WORKDIR

1 FROM: 指定基础镜像

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

FROM [--platform=<platform>] <image> [AS <name>]
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
FROM ubuntu
FROM centos:7.4

2 LABEL: 指定镜像元数据

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

LABEL <key>=<value> <key>=<value> <key>=<value>
LABEL version="1.0"
LABEL multi.label1="value1" multi.label2="value2" other="value3"

3 MAINTAINER: 指定维护者信息

此指令已过时,用LABEL代替

MAINTAINER <name>

4 RUN: 执行 shell 命令

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

#shell 格式: 相当于 /bin/sh -c <命令> 此种形式支持环境变量
RUN <命令> 

#exec 格式: 此种形式不支持环境变量,注意:是双引号,不能是单引号
RUN ["executable","param1","param2"...] 

#exec格式可以指定其它shell
RUN ["/bin/bash","-c","echo hello wang"]
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

RUN yum -y install epel-release \
     && yum -y install nginx \
     && echo "<h1> docker test nginx </h1>" > /usr/share/nginx/html/index.html

5 ENV: 设置环境变量

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

#变量赋值格式1
ENV <key> <value>   #此格式只能对一个key赋值,<key>之后的所有内容均会被视作其<value>的组成部分

#变量赋值格式2
ENV <key1>=<value1> <key2>=<value2> \  #此格式可以支持多个key赋值,定义多个变量建议使用,减少镜像层
 <key3>=<value3> ...
ENV myName jiutingqiu
ENV myName="jiutingqiu"

6 COPY: 复制文本

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

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

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

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

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

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

如果事先不存在,它将会被自动创建,这包括其父目录路径,即递归创建目录
COPY hom* /mydir/    
COPY hom?.txt /mydir/

7 ADD: 复制和解包文件

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

ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
ADD test /absoluteDir/
ADD --chown=55:mygroup files* /somedir/

8 CMD: 容器启动命令

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

# 使用 exec 执行,推荐方式,第一个参数必须是命令的全路径,此种形式不支持环境变量
CMD ["executable","param1","param2"] 

# 在 /bin/sh 中执行,提供给需要交互的应用;此种形式支持环境变量
CMD command param1 param2 

# 提供给 ENTRYPOINT 命令的默认参数
CMD ["param1","param2"]
CMD ["nginx", "-g", "daemon off;"]

9 ENTRYPOINT: 入口点

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

# 使用 exec 执行
ENTRYPOINT ["executable", "param1", "param2"...]

# shell中执行
ENTRYPOINT command param1 param2

ENTRYPOINT 不能被 docker run 提供的参数覆盖,而是追加,即如果docker run 命令有参数,那么参数全部都会作为ENTRYPOINT的参数
通常ENTRYPOINT指令配合脚本,主要用于为CMD指令提供环境配置
CMD ["-g","daemon off;"]
ENTRYPOINT ["/apps/nginx/sbin/nginx"]
#上面两条指令相当于ENTRYPOINT ["/apps/nginx/sbin/nginx","-g","daemon off;"]

10 ARG: 构建参数

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

ARG <name>[=<default value>]

11 VOLUME: 匿名卷

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

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

<容器内路径>如果在容器内不存在,在创建容器时会自动创建
<容器内路径>如果是存在的,同时目录内有内容,将会把此目录的内容复制到宿主机的实际目录
VOLUME [ "/data1","/data2" ]

12 EXPOSE: 暴露端口

指定服务端的容器需要对外暴露(监听)的端口号,以实现容器与外部通信。
EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会真正暴露端口,即不会自动在宿主进行端口映射

EXPOSE <port>
EXPOSE 80 443
EXPOSE 8080/udp 8080/tcp

13 WORKDIR: 指定工作目录

为后续的 RUN、CMD、ENTRYPOINT 指令配置工作目录,当容器运行后,进入容器内WORKDIR指定的默认目录,如该目录不存在,WORKDIR 会自行创建

WORKDIR /data

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

指定运行容器的用户名或 UID,在后续dockerfile中的 RUN ,CMD和ENTRYPOINT指令时使用此用户
可以用来配置当构建当前镜像的子镜像时,会自动触发执行的指令,但在当前镜像构建时,并不会执行,即延迟到子镜像构建时才执行
主要用于docker镜像的二次构建

ONBUILD [INSTRUCTION]

15USER: 指定当前用户

指定运行容器的用户名或 UID,在后续dockerfile中的 RUN ,CMD和ENTRYPOINT指令时使用此用户

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

4.构建镜像docker build 命令

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

docker build [OPTIONS] PATH | URL | -

-f              #Dockerfile文件名,默认为 PATH/Dockerfile
--force-rm      #总是删除中间层容器,创建镜像失败时,删除临时容器
--no-cache      #不使用之前构建中创建的缓存
-q              #不显示Dockerfile的RUN运行的输出结果
--rm=true       #创建镜像成功时,删除临时容器
-t              #设置注册名称、镜像名称、标签。格式为 <注册名称>/<镜像名称>:<标签>(标签默认为latest)
查看镜像的构建历史

docker history 镜像

5.利用Dockerfile构建基于CentOS编译nginx镜像

[root@c7-docker-node1-71 ~]# cat Dockerfile 
FROM centos
LABEL Lead_Author="jiutingqiu@www.elysia.media"

RUN cd /etc/yum.repos.d/ \
    && sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* \
    && sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-* \
    && yum -y install gcc pcre-devel openssl-devel zlib-devel wget make \
    && useradd -s /sbin/nologin nginx \
    && cd /usr/local/src/ \
    && wget https://nginx.org/download/nginx-1.22.1.tar.gz \
    && tar xf nginx-1.22.1.tar.gz \
    && cd nginx-1.22.1 \
    && ./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module \
    && make && make install \
    && chown -R nginx:nginx /apps/nginx \
    && ln -s /apps/nginx/sbin/nginx /usr/sbin/ \
    && mkdir /apps/nginx/run \
    && sed -i 's/^#pid.*/pid    \/apps\/nginx\/run\/nginx.pid\; \ndaemon off;/g' /apps/nginx/conf/nginx.conf
EXPOSE 80 443
CMD ["/sbin/nginx","-c","/apps/nginx/conf/nginx.conf"]

[root@c7-docker-node1-71 ~]# docker build -t c8_nginx_test:v1.0 .

[root@c7-docker-node1-71 ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
c8_nginx_test       v1.0                bc5881e469b5        20 seconds ago      470MB

1 测试

[root@c7-docker-node1-71 ~]# docker run -it -d --name test -p 80:80 c8_nginx_test:v1.0
48d484852ea27e73729ade080d6c40f3337bfcd24096315431b60c30a801aa29
[root@c7-docker-node1-71 ~]# docker ps -a
CONTAINER ID        IMAGE                COMMAND                  CREATED             STATUS              PORTS                         NAMES
48d484852ea2        c8_nginx_test:v1.0   "/sbin/nginx -c /app…"   2 seconds ago       Up 2 seconds        0.0.0.0:80->80/tcp, 443/tcp   test
[root@c7-docker-node1-71 ~]# curl 172.29.7.71
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注