dockerfile基础

一、dockerfile基础

1、官网拉取的镜像

  • docker pull centos:8.4.2105

  • 官网拉取的镜像都是最小化的

  • 拉取的镜像,有很多的命令不能使用,源也不能使用。所以的话,需要自己构建一下

  • 然后基于这个构建的镜像创建容器

  • 直接在阿里源上面找到即可

2、构建一个镜像

[root@docker ~]# cat dockerfile 
FROM centos:8.4.2105                                  
MAINTAINER qqq
RUN minorver=8.4.2105 \
&& sed -e "s|^mirrorlist=|#mirrorlist=|g"  -e "s|^#baseurl=http://mirror.centos.org/\$contentdir/\$releasever|baseurl=https://mirrors.aliyun.com/centos-vault/$minorver|g" -i.bak /etc/yum.repos.d/CentOS-*.repo

RUN yum -y install net-tools vim
CMD ["/bin/bash"]

# 默认是查找当前目录下面文件名为dockerfile的文件
# -t 构建镜像的标签,. 是当前路径
[root@docker ~]# docker build -t centos:v1.0 .

# 查看构建历史
[root@docker ~]# docker history centos:v1.0 
IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
65dac5a93139   5 minutes ago   CMD ["/bin/bash"]                               0B        buildkit.dockerfile.v0
<missing>      5 minutes ago   RUN /bin/sh -c yum -y install net-tools vim …   75.7MB    buildkit.dockerfile.v0
<missing>      5 minutes ago   RUN /bin/sh -c minorver=8.4.2105 && sed -e "…   17.6kB    buildkit.dockerfile.v0
<missing>      5 minutes ago   MAINTAINER qqq                                  0B        buildkit.dockerfile.v0
<missing>      3 years ago     /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B        
<missing>      3 years ago     /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B        
<missing>      3 years ago     /bin/sh -c #(nop) ADD file:805cb5e15fb6e0bb0…   231MB  

二、dockerfile指令

1、RUN指令

  • 有shell格式和exec格式

  • RUN shell命令

  • RUN ["可执行文件","参数1","参数2"]

2、build指令

  • docker build -f 文件名(绝对路径名) -t .(dockerfile处于的当前目录)

  • docker build -f /home/user/dockerfiles/myDockerfile -t myimage /home/user/dockerfiles

  • -f指定自定义的文件名,完整的路径,.表示dockerfile文件上一层的目录即可

  • 在这个上层目录下寻找dockerfile文件即可

  • 不是默认的文件名的话,加上-f参数

  • 一些文件都是根据这个上下文去寻找的,就必须放在这个上面中

docker build -f /home/dockerfile -t nginx:v1 /home(dockerfile处于的目录)

3、COPY指令

格式为COPY src dest

  • 将本地文件或者目录拷贝到容器里面

  • 目标路径,不存在,会自动创建

  • 是在上下文路径中寻找的,必须是相对路径

[root@docker ~]# cat d1
FROM centos:8.4.2105
COPY anaconda-ks.cfg /test/
COPY tmp/ /mnt/
CMD ["/bin/bash"]

# 发布一个nginx容器
[root@docker ~]# cat d2
FROM centos:8
RUN yum -y install nginx
COPY index.html /usr/share/nginx/html/
CMD ["nginx","-g","daemon off;"]

  • 以/结尾的话就是目录,否则就是文件

  • 注意的点
    src为目录的话,会将目录下面的内容和子目录拷贝到dest上面去

  • src为文件,并且dest也是文件的话,直接复制过去

4、ADD指令

格式为ADD src dest

  • 也是将本地的文件拷贝到容器里面

  • 还可以支持解压,将本地的压缩包解压到容器里面

  • 上下文路径的

[root@docker ~]# cat d2
FROM centos:8.4.2105
ADD tmp.tar.gz /mnt/
CMD ["/bin/bash"]

4、ENV指令

  • 定义环境变量,可以直接使用$进行调用

  • 提前定义好变量,适用于要提前传参的场景

ENV rootpasswd=123

5、USER指令

  • 格式为USER TOM

  • 指定用户登录

[root@docker ~]# cat d3
FROM centos:8
ENV abc=heheh
RUN yum -y install passwd
RUN useradd tom
RUN echo "123" | passwd --stdin tom
USER tom
CMD ["/bin/bash"]

6、VOLUME指令

  • 格式为VOLUME /data

  • 指定未来容器映射的目录

  • 作为一个容器挂载的目录

  • 然后就是创建容器的时候-v将本地的目录挂载到容器里面的目录即可

  • 需要手动指定

  • 不指定的话,会自动创建一个匿名卷挂载到容器的目录上面,而不能是挂载到容器文件,会报错的

VOLUME /data

# 创建容器的时候手动指定一下,即可挂载到容器里面的目录

7、ENTRYPOINT和CMD指令

  • 如果2个命令同时使用的话,CMD参数是作为ENTRYPOINT的参数来使用的

  • docker run的时候,没有手动输入命令参数,默认执行CMD参数,如果加了指定参数的话,就会覆盖掉CMD参数

  • CMD和ENTRYPOINT同时使用

[root@docker dd]# cat d1
FROM centos:8
ENTRYPOINT ["echo","hello"]
CMD ["cmd1"]

# 容器运行后,输出的为hello cmd1
[root@docker dd]# docker run -tid --name d1 d1:latest 
31343bd836c2a1230786fbbc504f06594d93cb8cf348c870703af96e12fce54e
[root@docker dd]# docker ps -a
CONTAINER ID   IMAGE       COMMAND             CREATED         STATUS                     PORTS     NAMES
31343bd836c2   d1:latest   "echo hello cmd1"   8 seconds ago   Exited (0) 6 seconds ago             d1
[root@docker dd]# docker logs d1 
hello cmd1


  • 手动指定CMD参数
[root@docker dd]# docker run -tid --name d2 d1 cmd2
eca0255734f40c8fd908a77d5b4a25a2d1d779813547a7af67510392fbc63cd5
[root@docker dd]# docker logs d2
hello cmd2

  • 有多个ENTRYPOINT的话需要以最后一个为准
[root@docker dd]# cat d1
FROM centos:8
ENTRYPOINT ["echo","hello"]
ENTRYPOINT ["echo","123"]  # 以这个为准
CMD ["cmd1"]

[root@docker dd]# docker run -tid --name d3 d2 
f7cc71a250749a817c7856960e8481b7e2238e4c15825257d5088f5e8ccb30a4
[root@docker dd]# docker logs d3
123 cmd1

  • --ENTRYPOINT参数可以覆盖掉原先的ENTRYPOINT参数,使用了这个参数的话,原先的CMD参数被忽略,需要重新传入参数

  • --ENTRYPOINT 后面必须是可执行的命令

  • 强行更改容器的命令

[root@docker dd]# docker run -tid --name d5 --entrypoint mkdir d1 /test
83b50c2f2be3a67b001911f9f39910b90bbc48ad7cf18b68272c77eb413bcb6b

[root@docker dd]# docker ps -a
CONTAINER ID   IMAGE       COMMAND             CREATED          STATUS                      PORTS     NAMES
83b50c2f2be3   d1          "mkdir /test"       3 seconds ago    Exited (0) 1 second ago               d5

8、EXPOSE指令

  • EXPOSE 端口号

  • 创建容器的时候需要-p指定端口号即可

  • 或者使用-P 会随机将宿主机的端口映射到容器里面指定的端口上面

9、WORKDIR指令

  • 切换工作目录

  • WORKDIR /app

三、实验

1、配置ssh镜像

1、ssh密码登录

  • 密钥文件生成出来

  • ssh服务器启动的是,会用到这些密钥,并于客户端进行加密连接

  • 默认一个镜像,里面都没有ssh软件包,所以需要安装,并且配置ssh密钥等等

[root@docker ~]# cat ssh1
FROM centos:8
RUN yum -y install passwd openssh-clients openssh-server net-tools
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
RUN ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key
RUN ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
RUN echo "123" | passwd --stdin root
EXPOSE 22
CMD ["/usr/sbin/sshd","-D"]

  • 上面这个是初级版本,然后远程登录一下,会有一些警告
[root@docker ~]# ssh root@172.17.0.2
root@172.17.0.2's password: 
"System is booting up. Unprivileged users are not permitted to log in yet. Please come back later. For technical details, see pam_nologin(8)."
[root@b9406140902f ~]#   

# 这个是因为pam_nologin模块的原因,会限制登录等等

  • 修改后的代码
[root@docker ~]# cat ssh2
FROM centos:8
RUN yum -y install passwd openssh-clients openssh-server net-tools
RUN ssh-keygen -A  # 可以生成主机缺少的密钥文件,保证了sshd服务正常启动了,因为容器启动的时候没有密钥文件,sshd服务就不能正常启动了
RUN echo "PermitRootLogin yes" >> /etc/ssh/sshd_config \
    && echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config \
    && sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config  # 禁用pam模块
RUN echo "123" | passwd --stdin root
EXPOSE 22
CMD ["/usr/sbin/sshd","-D"]  # sshd进程启动


# 这样就可以使用密码登录了

2、ssh免密登录

  • 配置ssh免密登录容器
[root@docker ~]# cat ssh3
FROM centos:8
RUN yum -y install passwd openssh-clients openssh-server net-tools
RUN ssh-keygen -A
RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config  # 如果添加 usepam模块禁用的话,ssh就不能免密登录了,可能与认证相关的模块需要开启
RUN sed -i 's/^\(account\s\+required\s\+pam_nologin.so\)/# \1/' /etc/pam.d/sshd  # 注释这一行就可以了,这个主要是控制用户登录
RUN mkdir -p /root/.ssh
COPY id_rsa.pub /root/.ssh/authorized_keys
RUN chmod 700 /root/.ssh && \
    chmod 600 /root/.ssh/authorized_keys && \
    chown -R root:root /root/.ssh
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]


# 免密登录会出现这个警告
"System is booting up. Unprivileged users are not permitted to log in yet. Please come back later. For technical details, see pam_nologin(8)."

# 解决方式就在上面,修改/etc/pam.d/sshd这个文件或者删除/run/nologin都可以
  • pam_nologin 是检查/etc/nologin或者/run/nologin存在的,如果存在非root用户登录被拒绝显示那个警告

  • 不存在的话则放行

  • 目的防止普通用户登录系统,避免系统未稳定时产生的异常操作

  • 还有一个就是容器中没有完整的init 系统,就会导致pam_nologin误判系统没有启动完成,就不允许登录,但是root用户可以跳过pam_nologin这个规则

2、配置一个基础容器镜像

  • 配置源,安装一些基础命令
# 因为原有的基础镜像里面的yum源不能使用,是过期的
[root@docker ~]# cat jichuimage 
FROM centos:8.4.2105
RUN minorver=8.5.2111 && sed -e "s|^mirrorlist=|#mirrorlist=|g" \
                             -e "s|^#baseurl=http://mirror.centos.org/\$contentdir/\$releasever|baseurl=https://mirrors.aliyun.com/centos-vault/$minorver|g" \
                             -i.bak /etc/yum.repos.d/CentOS-*.repo
RUN yum -y clean all && yum makecache 
RUN yum -y install net-tools && yum -y install vim && yum -y install epel-release
CMD ["/bin/bash"]

问题

  • dockerfile文件名一定是这个吗
# 不一定是这个名字,可以自定义

# 不是这个名字的时候,需要加上一个 -f 参数

  • -f 参数了,不在这个路径下又是怎样构建了
# 写绝对路径即可

posted @ 2025-07-14 17:24  乔的港口  阅读(11)  评论(0)    收藏  举报