目录
一、更新镜像
从已经存在的镜像中更新新镜像,并提交镜像使用。
语法结构:
docker commit 容器名/容器ID 新镜像名
[root@localhost ~]# docker images #查看镜像
REPOSITORY TAG IMAGE ID CREATED SIZE
max/ubuntu V1 cc7fb7ff9754 21 hours ago 122MB
nginx latest 605c77e624dd 22 months ago 141MB
ubuntu 20.04 ba6acccedd29 2 years ago 72.8MB
ubuntu latest ba6acccedd29 2 years ago 72.8MB
centos latest 5d0da3dc9764 2 years ago 231MB
[root@localhost ~]# docker run -it --name test ubuntu /bin/bash #运行新的容器test
root@0616c11e9c8d:/# apt-get update #在容器中更新软件列表
Get:1 http://security.ubuntu.com/ubuntu focal-security InRelease [114 kB]
...
Fetched 29.2 MB in 19s (1509 kB/s)
Reading package lists... Done
root@0616c11e9c8d:/# exit #更新完后退出
[root@localhost ~]# docker commit -m="update ubuntu" -a="max" test ubuntu:v1 #提交更新过test容器副本,并重新生成ubuntu:v1镜像,此时的容器test停止运行
sha256:83830b28425d7bdfea384933f9e4daba7d87dda657a88497feadd0b70eaf44e7
[root@localhost ~]# docker images #生成ubuntu:v1镜像
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu v1 83830b28425d 16 seconds ago 120MB
max/ubuntu V1 cc7fb7ff9754 21 hours ago 122MB
nginx latest 605c77e624dd 22 months ago 141MB
ubuntu 20.04 ba6acccedd29 2 years ago 72.8MB
ubuntu latest ba6acccedd29 2 years ago 72.8MB
centos latest 5d0da3dc9764 2 years ago 231MB
命令参数解释:
- -m:提交的描述信息
- -a:指定镜像作者
- max/ubuntu:V1:所要创建的镜像名
二、Dockerfile
1. Dockerfile含义
Dockerfile构建镜像的文本文件,文件内容包含构建镜像所需要的指令和说明。
2. 构建镜像
2.1 构建流程
docker build命令根据给定的Dockerfile的上下文顺序构建Docker镜像。Dockerfile文件中所有参数大写。
创建镜像所在目录和Dockerfile文件:
# mkdir /test
# cd /test
# vim Dockerfile
FROM 基础镜像名 #告知docker镜像是什么
MAINTAINER 作者 #可选项,描述作者邮箱
RUN 镜像内的操作 #在镜像内做什么操作
构建镜像:
# docker build -t 镜像名 . #-t表示:标识新建的镜像,. 表示:Dockerfile文件所在目录
2.2 构建OS镜像使用systemctl命令
构建Centos7使用systemctl命令。docker构建OS默认没有systemctl命令。
1.官网下载Centos镜像,运行容器centos-3查看容器内时间与宿主机时间不同,并且systemctl命令不存在。
[root@localhost ~]# date #查看宿主机时间
Thu Nov 16 11:30:45 CST 2023
[root@localhost ~]# docker pull centos #获取Docker Hub网站centos最新的镜像
[root@localhost ~]# docker run -it --name centos-3 centos /bin/bash #运行容器centos-3
[root@f16a4fe39004 /]# date #容器内时间与宿主机不同
Thu Nov 16 03:31:21 UTC 2023
[root@f16a4fe39004 /]# exit #退出容器
[root@localhost centos]# docker start centos-3 #运行容器
centos-3
[root@localhost centos]# docker exec -it centos-3 /bin/bash #进入容器
[root@f16a4fe39004 /]# systemctl start ngixn #使用该命令检查systemctl使用可以使用
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
[root@f16a4fe39004 /]# exit
2.使用Dockerfile文档构建操作系统使用systemctl命令。
[root@localhost ~]# mkdir /centos #创建centos目录
[root@localhost ~]# cd /centos
[root@localhost centos]# vim Dockerfile #编写Dockerfile文档
FROM centos:7
ENV container docker
ENV TZ=Asia/Shanghai
ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US:en
ENV LC_ALL=en_US.UTF-8
RUN yum -y swap -- remove fakesystemd -- install systemd systemd-libs && yum -y update; yum clean all; \
(cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;
VOLUME [ "/sys/fs/cgroup" ]
CMD ["/usr/sbin/init"]
Dockerfile文档解释逐行说明:
- 指定基础镜像为Docker Hub的CentOS 7镜像
- 设置容器环境为docker,为区分不同环境
- 设置时区为Asia/Shanghai,确保容器时区与上海时区一致
- 设置默认语言为en_US.UTF-8(美国英语),这将影响容器中各种程序和工具使用的语言设置
- 设置环境的语言为en_US:en(美国英语),这用来控制一些程序和工具的具体语言
- 设置地区和字符集为en_US.UTF-8,确保容器中的所有程序和工具使用正确的地区和字符集
- 将fakesystemd包替换为真正的systemd包,fakesystemd是CentOS Docker映像中的一个特殊包,它满足对Systemd的依赖,而不实际安装Systemd。并且更新所有软件包,删除不必要的文件,并清理yum缓存。移除不必要的systemd单位文件以减小镜像大小
- 将 /sys/fs/cgroup 目录设置为卷,以便在运行容器时可以从宿主机上挂载
- 指定容器启动时的默认命令。此情况下,它是systemd的init进程
3.在Dockerfile目录下构建镜像。
语法结构:
docker build -t 镜像名 Dockerfile所在目录
[root@localhost centos]# docker build --rm -t cnetos:v1 . #构建镜像cnetos:v1
[+] Building 111.0s (6/6) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.3s
=> => transferring dockerfile: 803B 0.0s
=> [internal] load .dockerignore 0.4s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/centos:7 15.7s
=> CACHED [1/2] FROM docker.io/library/centos:7@sha256:9d4bcbbb213dfd745b58be38b13b996ebb5ac315fe75711bd618426a630e0987 0.0s
=> [2/2] RUN yum -y swap -- remove fakesystemd -- install systemd systemd-libs && yum -y update; yum clean all; (cd /li 89.3s
=> exporting to image 5.1s
=> => exporting layers 5.1s
=> => writing image sha256:43bfe8bfce3651ac36260e1810494a45908cc9cf03c2777d8a385a0d66bcc97c 0.0s
=> => naming to docker.io/library/cnetos:v1 0.0s
[root@localhost centos]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
cnetos v1 43bfe8bfce36 About an hour ago 367MB
命令解释说明:
- --rm:构建过程成功后删除中间环节的容器
- -t:定义要创建的目标镜像名
- cnetos:v1:创建镜像名
- .:Dockerfile文件所在目录,指定Dockerfile的绝对路径
4.运行容器centos-1,进入容器查看容器时间与宿主机时间相同。尝试使用systemctl开启nginx(nginx未安装但不影响测试)报错,不允许操作。
[root@localhost centos]# docker run -itd --name centos-1 cnetos:v1 /bin/bash
9d921e65f31fc997507bfc43770382b01aef03c1c3fe13157a04e4ea9c533fbe
[root@localhost centos]# docker exec -it centos-1 /bin/bash
[root@9d921e65f31f /]# date
Thu Nov 16 11:28:29 CST 2023
[root@9d921e65f31f /]# systemctl start nginx
Failed to get D-Bus connection: Operation not permitted
[root@9d921e65f31f /]# exit
5.解决4不能操作systemctl命令问题。使用特权模式运行容器报错为未发现nginx服务。
[root@localhost centos]# docker run -itd --name centos-2 --privileged cnetos:v1 /sbin/init
c610ffef4264eec128236c0673166e5aa2e95cc5ce130d4b3a76725b027dad9e
[root@localhost centos]# docker exec -it centos-2 /bin/bash
[root@c610ffef4264 /]# date
Thu Nov 16 11:30:23 CST 2023
[root@c610ffef4264 /]# systemctl start nginx
Failed to start nginx.service: Unit not found.
[root@c610ffef4264 /]# exit
命令解释说明:
- --privileged:特权模式
- /sbin/init:搭配特权模式使用登录shell
2.3 构建Nginx
1.创建Dockerfile文件:
[root@localhost ~]# mkdir /nginx
[root@localhost ~]# cd /nginx
[root@localhost nginx]# vim Dockerfile
FROM centos:7
ENV NG_VERSION nginx-1.22.1
RUN yum -y install wget \
&& wget http://nginx.org/download/$NG_VERSION.tar.gz \
&& yum -y install epel-release \
&& yum -y install gcc openssl openssl-devel pcre-devel zlib-devel make
ADD $NG_VERSION.tar.gz /opt
WORKDIR /opt/$NG_VERSION
RUN ./configure --prefix=/usr/local/nginx \
&& make && make install && rm -rf /opt/$NG_VERSION
WORKDIR /usr/local/nginx
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/nginx/sbin
EXPOSE 80 443
CMD ["nginx","-g","daemon off;"]
Dockerfile文档解释逐行说明:
- 指定基础镜像为Docker Hub的CentOS 7镜像
- 定义NG_VERSION变量为nginx-1.22.1
- 下载wget,使用wget获取nginx-1.22.1tar包,下载nginx依赖项
- 将下载的nginx-1.22.1tar包解压并拷贝到容器
- 指定工作目录为/opt/nginx-1.22.1
- 配置环境,配置完后进行编译安装,删除/opt/nginx-1.22.1目录
- 指定工作目录为/usr/local/nginx
- 定义变量PATH关联可执行文件
- 容器运行时暴露的端口80和443
- 容器创建时的默认命令
2.构建镜像:
[root@localhost nginx]# docker build -t nginx-1 .
[+] Building 267.5s (11/11) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.1s
=> => transferring dockerfile: 596B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/centos:7 0.2s
=> CACHED [1/6] FROM docker.io/library/centos:7@sha256:9d4bcbbb213dfd745b58be38b13b996e 0.0s
=> [internal] load build context 0.1s
=> => transferring context: 42B 0.0s
=> [2/6] RUN yum -y install wget && wget http://nginx.org/download/nginx-1.22.1.t 198.8s
=> [3/6] ADD nginx-1.22.1.tar.gz /opt 0.2s
=> [4/6] WORKDIR /opt/nginx-1.22.1 0.1s
=> [5/6] RUN ./configure --prefix=/usr/local/nginx && make && make install && rm - 60.5s
=> [6/6] WORKDIR /usr/local/nginx 0.1s
=> exporting to image 7.4s
=> => exporting layers 7.4s
=> => writing image sha256:97362fc65ebf70710687559c73865e82f47e806de798f3360cfed7171e12 0.0s
=> => naming to docker.io/library/nginx-1 0.0s
命令解释说明:
- docker build:构建镜像
- -t:定义要创建的目标镜像名
- nginx-1:创建镜像名
- .:Dockerfile文件所在目录,指定Dockerfile的绝对路径
3.运行镜像:
[root@localhost nginx]# docker run -itd --name nginx-v1 -p 84:80 nginx-1
9766440a1b357e3a317d3abc8df0e21bdd8a2eb518d7b6ea2bc7eafe553fe8ca
[root@localhost nginx]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9766440a1b35 nginx-1 "nginx -g 'daemon of…" 3 seconds ago Up 2 seconds 0.0.0.0:84->80/tcp, :::84->80/tcp nginx-v1
命令解释说明:
- docker run:运行容器
- -itd:提供交互式模式的伪输入终端并且在后台运行打印容器id
- --name nginx-v1:创建容器名
- -p 84:80:宿主机端口84映射给容器端口80,不做端口映射无法访问容器
- nginx-1:使用的镜像
4.浏览器访问容器:
3. Dockerfile 基础指令说明
指令 | 说明 |
---|---|
FROM | 指定基础镜像 |
LABEL | 指定Dockerfile的作者(可选项) |
RUN | 在镜像中执行命令 |
CMD | 为启动的容器执行默认需要运行的程序(可覆盖) |
EXPOSE | 容器运行时暴露的端口 |
ENV | 在容器内部设置环境变量 |
ADD | 将文件、目录或远程URL复制到镜像中,压缩文件会自动解压 |
COPY | 将文件或目录复制到镜像中,压缩文件手动解压 |
WORKDIR | 设置后续指令的工作目录 |
USER | 指定后续指令的用户上下文 |
LABEL
用来给镜像添加一些元数据(metadata),以键值对的形式。
格式:LABEL <key>=<value> <key>=<value> <key>=<value> ...
例:
LABEL image.authors="max"
CMD
用于运行程序,于 RUN类似,但RUN在 docker build使用,CMD 在docker run 时运行。如果 Dockerfile 中存在多个 CMD 指令,仅最后一个生效。
格式: CMD ["<可执行文件或命令>","<param1>","<param2>",...]
例:
CMD ["nginx","-g","daemon off;"]
EXPOSE
声明端口。帮助使用者理解镜像服务的守护端口,以方便配置映射。使用随docker run -P 命令运行容器,会自动随机映射 EXPOSE 的端口。
格式:EXPOSE <端口1> [<端口2>...]
ENV
定义环境变量,便于在后续的指令中,可以使用这个环境变量。
格式:ENV <key> <value> 或 ENV <key1>=<value1> <key2>=<value2>...
例:
ENV NODE_VERSION nginx-1.22.1 #设置NODE_VERSION=nginx-1.22.1
RUN wget http://nginx.org/download/$NG_VERSION.tar.gz #后续指令引用变量
ADD
从目录中复制文件或者目录到容器指定路径。与COPY不同之处是,在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
格式: ADD [--chown=<user>:<group>] "<源路径1>",... "<目标路径>"
例:
ADD nginx-1.22.1.tar.gz /opt
COPY
从目录中复制文件或者目录到容器指定路径。
格式: COPY [--chown=<user>:<group>] "<源路径1>",... "<目标路径>"
[--chown=<user>:<group>]:可选,用户改变复制到容器内文件的拥有者和属组
例:
COPY nginx-1.22.1 /opt
WORKDIR
指定工作目录。它会在构建镜像的每一层中存在,以后各层的当前目录就被改为指定的目录,如目录不存在,WORKDIR 会建立目录。docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。
格式:WORKDIR <工作目录路径>
USER
指定执行后续命令的用户和用户组,用户和用户组需要提前被创建。
格式:USER <用户名>[:<用户组>]