目录

使用dockerfile创建镜像

使用dockerfile创建镜像

1.什么是Dockerfile

Dockerfile 是一个用于指导 Docker 镜像构建过程的脚本文件。它通过一系列指令来详细描述了构建镜像所需的步骤和配置细节。利用 Dockerfile,我们可以精确地设定容器的运行环境,安装必要的软件,复制项目文件,以及配置环境变量等。

Dockerfile 的优势在于其可重复性和自动化,使得应用程序的容器化过程既高效又可靠。通过将构建过程代码化,我们能够对构建步骤进行版本控制,并在不同的环境中复现相同的镜像。

Dockerfile 的组成通常包括以下几个方面:指定基础镜像、提供维护者信息、执行镜像构建指令以及定义容器启动时要运行的命令。

在 Dockerfile 中,指令是按照从上到下的顺序执行的,且首个非注释指令必须是 FROM,用以指定基础镜像。Dockerfile 中的注释以“#”开头。

Dockerfile 支持多种指令,例如 RUN、CMD、FROM、EXPOSE、ENV 等,这些指令帮助我们定义镜像的操作系统、安装软件、设置环境变量等。

编写完 Dockerfile 后,我们可以通过执行 docker build 命令并指定 Dockerfile 的位置来构建镜像。Docker 引擎将按照 Dockerfile 中的指令逐步构建,最终生成一个新的镜像。

综上所述,Dockerfile 是一个关键工具,它通过简洁明了的文本指令,帮助我们自动化和标准化 Docker 镜像的构建过程,从而简化了容器化应用程序的部署工作。

2.Dockerfile 中常用的指令

指令说明
FROM指定基础镜像
MAINTAINER设置维护者信息
RUN在镜像中执行命令
CMD指定容器启动时要执行的命令
ENTRYPOINT与 CMD 类似,但不会被 docker run 命令行参数覆盖
COPY复制文件或目录到镜像中
ADD复制文件或目录到镜像中,支持远程 URL 和解压缩功能
ENV设置环境变量
ARG定义构建时的变量,可以通过 –build-arg 参数传递
WORKDIR设置工作目录
USER指定运行容器时的用户名或 UID
EXPOSE声明容器运行时需要监听的端口
HEALTHCHECK定义容器的健康检查命令
VOLUME声明容器中的挂载点
LABEL为镜像添加元数据

注意事项:

FROM

  • 尽量使用官方镜像作为基础镜像,以确保稳定性和安全性。
  • 指定镜像时,最好使用具体标签(例如 ubuntu:20.04 而不是 ubuntu:latest ),以避免构建时的不一致性。

MAINTAINER (已废弃,推荐使用 LABEL)

  • 请注意,MAINTAINER 指令已被废弃,现在推荐使用 LABEL 指令来设置维护者信息。

RUN

  • 为了保持 Dockerfile 的可读性和可维护性,尽量使用 && 来链式执行命令,并使用 \ 来换行。
  • 尽可能使用 RUN apt-get clean 来清理缓存,减少镜像大小。

CMD

  • CMD 指令的目的是为执行容器提供默认值,如果 docker run 指定了命令,CMD 会被覆盖。
  • 当 Dockerfile 中有多个 CMD 指令时,只有最后一个 CMD 会生效。

ENTRYPOINT

  • ENTRYPOINT 与 CMD 结合使用可以设置容器启动时要执行的默认命令和参数。
  • 使用 ENTRYPOINT ["executable", "param1", "param2"] 的形式可以确保 docker run 的参数被追加到 param1 , param2 后面。

COPY 和 ADD

  • 尽可能使用 COPY 而不是 ADD,除非你需要 ADD 的额外功能(如解压缩)。
  • 为了提高可读性,请明确指定源路径和目标路径。

ENV

  • 使用 ENV 来设置环境变量,可以在后续的指令中使用这些变量。
  • 尽量将环境变量设置在 Dockerfile 的顶部,以便于其他指令引用。

ARG

  • ARG 指令定义的变量只在构建时有效,容器运行时不可用。
  • 使用 ARG 定义的变量可以在 docker build 时通过 --build-arg 传递。

WORKDIR

  • 使用 WORKDIR 而不是多个 RUN 指令中的 cd ,以确保路径的清晰性和一致性。

USER

  • 使用 USER 指令来指定运行容器的用户,以减少安全风险。

EXPOSE

  • EXPOSE 指令只是声明容器将监听指定的端口,并不会自动映射端口到宿主机。

HEALTHCHECK

  • 使用 HEALTHCHECK 来检测容器的健康状态,这对于自动重启失败的容器很有用。

VOLUME

  • 使用 VOLUME 来管理容器的数据持久化,避免数据丢失。

LABEL

  • 使用 LABEL 来添加元数据,便于组织镜像和记录版本信息。

这些指令可以根据需要灵活组合,构建出符合需求的 Docker 镜像。请注意,Dockerfile 中的指令顺序很重要,因为每个指令都会创建一个新的镜像层,而后续的指令将基于前面的镜像层进行操作。

更详细的指令说明和用法,请参考 Docker 官方文档:

3.dockerfile基本结构和构建镜像原则

3.1 基本结构

https://i-blog.csdnimg.cn/direct/e03794164b9144ef8a5fee7203f12081.png

3.2 构建基本原则

dockerfile构建镜像需要遵循一下原则:

  • 单一职责:每个层级只做每个层级的事
  • 提供注释信息:最好提供注释信息,以便他人理解
  • 保持容器最小化
  • 合理选择基础镜像:基础镜像的选择很重要,尽量选择成熟易用的基础镜像版本
  • 最小化镜像层数:镜像层数不宜过多,尽量精简,否则容易出错,也可能会影响加载速度

https://i-blog.csdnimg.cn/direct/4837ac5ac87443f38b49608932b003c1.png

通过上面的示例图可以看出,每多一行命令,镜像的内容就多一层。

其他注意事项:

  • 尽量减少镜像层数,可以通过合并 RUN 指令来实现。
  • 使用 .dockerignore 文件排除不必要的文件和目录,减少构建上下文的大小。
  • 保持 Dockerfile 的简洁性,避免在其中执行复杂的操作,尽可能在构建上下文中准备数据。
  • 定期更新基础镜像以包含最新的安全补丁。

4.Dockerfile使用示例

4.1 基于centos8镜像构建nginxWeb服务镜像

以下是一个简单的 Dockerfile示例,以构建一个基于 centos 的配置web服务的镜像:

1.创建构建上下文目录:

[root@open-Euler3 ~]# mkdir dockerfile_test

2.本地添加nginx测试界面用于COPY

[root@open-Euler3 ~]# echo "nginx test" > dockerfile_test/index.html

3.编写Dockerfile文件

[root@open-Euler3 dockerfile_test]# cat Dockerfile
# 1. 第一行必须指定基础镜像信息
ARG VER=8
FROM centos:${VER}

# 2. 作者信息
LABEL maintainer="openlab <openlab@123.com>"

# 3. 安装 nginx
RUN mkdir -p /etc/yum.repos.d/bak_repo && \
    mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/bak_repo/ 2>/dev/null || true && \
    curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-8.repo && \
    dnf clean all && \
    dnf makecache && \
    dnf install -y nginx
  
# 4. 复制静态文件
COPY index.html /usr/share/nginx/html

# 5. 暴露端口
EXPOSE 80 443

# 6. 启动服务
ENTRYPOINT ["/usr/sbin/nginx", "-g", "daemon off;"]

4.docker build 构建镜像

https://i-blog.csdnimg.cn/direct/72ee4b0741724ec19059f87e68a2b2bf.png

注意: -t 选项指定构建出镜像的标签 最后的 “.” 指定的是当前目录,也就是构建上下文目录,Dockerfile所在的目录

5.查看构建的镜像

[root@open-Euler3 dockerfile_test]# docker images
REPOSITORY                   TAG       IMAGE ID       CREATED         SIZE
centos_nginx                 latest    7ca95c53855e   2 minutes ago   342MB
ubuntu                       18.04     f9a80a55f492   21 months ago   63.2MB
reg.yym.com/openlab/ubuntu   18.04     f9a80a55f492   21 months ago   63.2MB
centos                       8         5d0da3dc9764   3 years ago     231MB

6.启动容器并进行测试:

https://i-blog.csdnimg.cn/direct/61d91dd2428a45b9bee1d14edd6b6aeb.png

4.2 基于ubuntu镜像配置SSH服务

要求:

1、基础镜像ubuntu:18.04。

2、替换为国内的安装源(比如阿里或163)。

3、安装openssh-server。

4、允许root用户远程登录。

5、暴露端口22。

6、服务开机自启动。

1.创建构建上下文目录:

[root@open-Euler3 dockerfile_ssh]# pwd #这是我的构建上下文位置
/root/dockerfile_ssh

2.文件准备

1)apt源:

[root@open-Euler3 dockerfile_ssh]# cat 163.list
deb http://mirrors.163.com/ubuntu/ bionic main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ bionic-security main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ bionic-updates main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ bionic-backports main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ bionic main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ bionic-security main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ bionic-updates main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ bionic-backports main restricted universe multiverse

2)客户端公钥文件

[root@open-Euler3 dockerfile_ssh]# ssh-keygen -f ~/.ssh/id_rsa -P '' -q #生成公私钥
[root@open-Euler3 dockerfile_ssh]# cp ~/.ssh/id_rsa.pub ./authorized_keys

3)准备启动脚本文件

[root@open-Euler3 dockerfile_ssh]# cat run.sh
#!/bin/bash
/usr/sbin/sshd -D
[root@open-Euler3 dockerfile_ssh]# chmod +x run.sh

4)编写Dockerfile文件

[root@open-Euler3 dockerfile_ssh]# vim Dockerfile
FROM ubuntu:18.04

MAINTAINER "kongd <kongd@11.com>"

RUN mv /etc/apt/sources.list /etc/apt/sources.bak
COPY aliyun.list /etc/apt/sources.list.d/aliyun.list
RUN apt update && apt install -y openssh-server && mkdir -p /var/run/sshd
RUN sed -ri 's/session    required     pam_loginuid.so/#session    required     pam_loginuid.so/' /etc/pam.d/sshd
COPY run.sh /run.sh
RUN chmod +x /run.sh
RUN mkdir /root/.ssh
COPY authorized_keys /root/.ssh/authorized_keys

EXPOSE 22/tcp

CMD ["/run.sh"]

docker build 构建镜像)

https://i-blog.csdnimg.cn/direct/8e778a9fb08e4dd9b74cae29d600cfca.png

查看镜像:

[root@open-Euler3 dockerfile_ssh]# docker images
REPOSITORY                   TAG       IMAGE ID       CREATED         SIZE
ssh1_image                   latest    98ea77f917f0   4 minutes ago   248MB
centos_nginx                 latest    fb1d61ed3b60   3 hours ago     342MB
ubuntu                       18.04     f9a80a55f492   21 months ago   63.2MB
reg.yym.com/openlab/ubuntu   18.04     f9a80a55f492   21 months ago   63.2MB
centos                       8         5d0da3dc9764   3 years ago     231MB

通过构建的镜像启动一个容器:

[root@open-Euler3 dockerfile_ssh]# docker run -itd --name ssh1_c1 -p 10022:22 ssh1_image
cfec71666b634dfbfea43427cf1846d9516bcc3a9806f923a6391e560a721319
[root@open-Euler3 dockerfile_ssh]# docker ps -a
CONTAINER ID   IMAGE        COMMAND     CREATED         STATUS         PORTS                                     NAMES
cfec71666b63   ssh1_image   "/run.sh"   3 seconds ago   Up 3 seconds   0.0.0.0:10022->22/tcp, :::10022->22/tcp   ssh1_c1

测试ssh免密登录:

https://i-blog.csdnimg.cn/direct/1f99f5530ca74ee3bac4431ee1f410df.png

可以看到直接通过映射后的宿主机IP+端口登录到容器的shell上。