什么是 Dockerfile?

Dockerfile 是用来构建 Docker 镜像的构建文件, 是由一系列的命令和参数构成的脚本

通过指令的方式构建镜像

Dockerfile 主体内容分为四部分:基础镜像信息、 维护者信息、 镜像操作指令和容器启动时执行指令。

构建Dockerfile步骤

编写 Dockerfile 文件

docker built 构建镜像

docker run 创建容器

Dockfile 文件的注意事项

Docker 以从上到下的顺序运行 Dockerfile 的指令。为了指定基本映像,第一条指令必须是 FROM。

每条保留字指令都必须是大写字母, 并且后面要跟随至少一个参数

指令按照从上到下的顺序执行

每条指令可用 # 添加注释

每条指令都会创建一个新镜像层, 并对镜像进行提交

dockerfile的保留字指令

主要保留指令:

指令含义:
FROM    

指定基础镜像,必须为第一个命令

格式:   

FROM <image>   

FROM <image>:<tag>   

FROM <image>@<digest>

示例:FROM mysql:5.6 注: tag或digest是可选的,如果不使用这两个值时,会使用latest版本的基础镜像


MAINTAINER  

维护者信息

格式: MAINTAINER <name>

示例: MAINTAINER bertwu MAINTAINER xxx@163.com MAINTAINER bertwu <xxx@163.com>


RUN    

构建镜像docker build时执行的命令

RUN用于在构建镜像时执行命令,其有以下两种命令执行方式:
shell执行
格式:
    RUN <command>
exec执行
格式:
    RUN ["executable", "param1", "param2"]
示例:
    RUN ["executable", "param1", "param2"]
    RUN apk update
    RUN ["/etc/execfile", "arg1", "arg1"]
注:RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,
可以在构建时指定--no-cache参数,如:docker build --no-cache
 


ADD    

将本地文件添加到容器中,tar 类型文件会自动解压(网络压缩资源不会被解压)

格式:
    ADD <src>... <dest>
    ADD ["<src>",... "<dest>"] 用于支持包含空格的路径
示例:
    ADD hom* /mydir/          # 添加所有以"hom"开头的文件
    ADD hom?.txt /mydir/      # ? 替代一个单字符,例如:"home.txt"
    ADD test relativeDir/     # 添加 "test" 到 `WORKDIR`/relativeDir/
    ADD test /absoluteDir/    # 添加 "test" 到 /absoluteDir/
 


COPY    

功能类似ADD,但是是不会自动解压文件,也不能访问网络资源


CMD    

在docker run时会执行的命令,如果存在多个则仅最后一个生效。

格式:
    CMD ["executable","param1","param2"] (执行可执行文件,优先)
    CMD ["param1","param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)
    CMD command param1 param2 (执行shell内部命令)
示例:
    CMD echo "This is a test." | wc -l
    CMD ["/usr/bin/wc","--help"]

注:CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。

ENTRYPOINT

配置容器,使其可执行化。配合CMD可省去"application",只使用参数。

格式:
    ENTRYPOINT ["executable", "param1", "param2"] (可执行文件, 优先)
    ENTRYPOINT command param1 param2 (shell内部命令)
示例:
    FROM ubuntu
    ENTRYPOINT ["ls", "/usr/local"]
    CMD ["/usr/local/tomcat"]
  之后,docker run 传递的参数,都会先覆盖cmd,然后由cmd 传递给entrypoint ,做到灵活应用

注:ENTRYPOINT与CMD非常类似,不同的是通过docker run执行的命令不会覆盖ENTRYPOINT,
 而docker run命令中指定的任何参数,都会被当做参数再次传递给CMD。
 Dockerfile中只允许有一个ENTRYPOINT命令,多指定时会覆盖前面的设置,
 而只执行最后的ENTRYPOINT指令。
 通常情况下,    ENTRYPOINT 与CMD一起使用,ENTRYPOINT 写默认命令,
 

LABEL    

用于为镜像添加元数据

格式:
    LABEL <key>=<value> <key>=<value> <key>=<value> ...
示例:
  LABEL version="1.0" description="这是一个Web服务器" by="IT笔录"
注:
  使用LABEL指定元数据时,一条LABEL指定可以指定一或多条元数据,指定多条元数据时不同元数据
  之间通过空格分隔。推荐将所有的元数据通过一条LABEL指令指定,以免生成过多的中间镜像
 


ENV    

设置环境变量

格式:
    ENV <key> <value>  #<key>之后的所有内容均会被视为其<value>的组成部分,因此,一次只能设置一个变量
    ENV <key>=<value> ...  #可以设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<key>中包含空格,可以使用\来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行
示例:
    ENV myName John Doe
    ENV myDog Rex The Dog    
    ENV myCat=fluffy
 


EXPOSE    

指定于外界交互的端口

格式:
    EXPOSE <port> [<port>...]
示例:
    EXPOSE 80 443
    EXPOSE 8080    
    EXPOSE 11211/tcp 11211/udp
注:  EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口

如果没有暴露端口,后期也可以通过-p 8080:80方式映射端口,但是不能通过-P形式映射


VOLUME  

 用于指定持久化目录

格式:
    VOLUME ["/path/to/dir"]
示例:
    VOLUME ["/data"]
    VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"
注:一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:
1 卷可以容器间共享和重用
2 容器并不一定要和其它容器共享卷
3 修改卷后会立即生效
4 对卷的修改不会对镜像产生影响
5 卷会一直存在,直到没有任何容器在使用它



WORKDIR    

工作目录,类似于cd命令

格式:
    WORKDIR /path/to/workdir
示例:
    WORKDIR /a  (这时工作目录为/a)
    WORKDIR b  (这时工作目录为/a/b)
    WORKDIR c  (这时工作目录为/a/b/c)
注: 
  通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY
  等命令都会在该目录下执行。在使用docker run运行容器时,可以通过-w参数覆盖构建时所设置的工作目录
 

USER

指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户。使用USER指定用户时,可以使用用户名、UID或GID,或是两者的组合。当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户

格式:  
USER user  
USER user:group  
USER uid  
USER uid:gid  
USER user:gid  
USER uid:group
示例:      
     USER www
 注:
  使用USER指定用户后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT都将使用该用户。
  镜像构建完成后,通过docker run运行容器时,可以通过-u参数来覆盖所指定的用户。
 

ARG

用于指定传递给构建运行时的变量(给dockerfile传参),相当于构建镜像时可以在外部为里面传参

格式:

<name>[=<default value>]

示例: ARG site ARG build_user=www


ONBUILD    

用于设置镜像触发器

格式: 
    ONBUILD [INSTRUCTION]
示例:
  ONBUILD ADD . /app/src
  ONBUILD RUN /usr/local/bin/python-build --dir /app/src
注:
  NNBUID后面跟指令,当当前的镜像被用做其它镜像的基础镜像,该镜像中的触发器将会被钥触发
 

为什么要使用Dockerfile

问题:在dockerhub中官方提供很多镜像已经能满足我们的所有服务了,为什么还需要自定义镜像
核心作用:日后用户可以将自己应用打包成镜像,这样就可以让我们应用进行容器运行.还可以对官方镜像做扩展,以打包成我们生产应用的镜像。

Dockerfile-LMLPHP

 实验:

mkdir /opt/sshd
cd /opt/sshd

vim Dockerfile
#第一行必须指明基于的基础镜像
FROM centos:7
#作者信息
MAINTAINER this is ssh image <wl>
#镜像的操作指令
RUN yum -y update
RUN yum -y install openssh* net-tools lsof telnet passwd
RUN echo 'abc1234' | passwd --stdin root
RUN sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config                        #不使用PAM认证
RUN sed -ri '/^session\s+required\s+pam_loginuid.so/ s/^/#/' /etc/pam.d/sshd    #取消pam限制
RUN ssh-keygen -t rsa -A                                                        #生成密钥认证文件
RUN mkdir -p /root/.ssh && chown root.root /root && chmod 700 /root/.ssh
EXPOSE 22
CMD ["/usr/sbin/sshd" , "-D"]            #/usr/sbin/sshd -D 用于前台启动sshd服务


//生成镜像
docker build -t sshd:centos .

//启动容器并修改root密码
docker run -d -P sshd:centos
docker ps -a
ssh localhost -p 49155

---------------------Systemctl镜像-------------------------------------
mkdir /opt/systemctl
cd /opt/systemctl

vim Dockerfile

FROM sshd:centos
MAINTAINER this is systemctl image <wl>
ENV container docker
#除了systemd-tmpfiles-setup.service,删除其它所有文件
RUN (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"]


//生成镜像
docker build -t systemd:centos .

//启动容器,并挂载宿主机目录挂载到容器中,和进行初始化
docker run --privileged -d -P -v /sys/fs/cgroup:/sys/fs/cgroup:ro systemd:centos /sbin/init
#--privileged:使container内的root拥有真正的root权限。否则,container内的root只是外部的一个普通用户权限。

docker ps -a

//进入容器
docker exec -it a0d624d2bfa9 bash

systemctl status sshd

方法二:
docker run --privileged -it -P -v /sys/fs/cgroup:/sys/fs/cgroup:ro systemd:centos /sbin/init &

----------------nginx镜像------------------------------
mkdir /opt/nginx
cd /opt/nginx/
cp /opt/nginx-1.12.0.tar.gz /opt/nginx

vim Dockerfile

#基于基础镜像
FROM centos:7
#用户信息
MAINTAINER this is nginx image <wl>
#添加环境包
RUN yum -y update
RUN yum -y install pcre-devel zlib-devel gcc gcc-c++ make
RUN useradd -M -s /sbin/nologin nginx
#上传nginx软件压缩包,并解压
ADD nginx-1.12.0.tar.gz /opt/
#指定工作目录
WORKDIR /opt/nginx-1.12.0
RUN ./configure \
--prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-http_stub_status_module && make && make install
ENV PATH /usr/local/nginx/sbin:$PATH
#指定http和https端口
EXPOSE 80
EXPOSE 443
RUN echo "daemon off;" >> /usr/local/nginx/conf/nginx.conf            #关闭 nginx 在后台运行
#添加宿主机中run.sh到容器中
ADD run.sh /run.sh
RUN chmod 755 /run.sh
CMD ["/run.sh"]
#CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]


vim run.sh
#!/bin/bash
/usr/local/nginx/sbin/nginx

//创建新镜像
docker build -t nginx:centos .

docker run -d -P nginx:centos

docker ps -a
5df9e4383b96        nginx:centos           "/run.sh"           15 seconds ago      Up 15 seconds       0.0.0.0:32769->80/tcp, 0.0.0.0:32768->443/tcp   silly_davinci

http://192.168.100.10:32769

------------------tomcat 镜像---------------------------
mkdir /opt/tomcat
cd /opt/tomcat
cp /opt/jdk-8u91-linux-x64.tar.gz /opt/tomcat
cp /opt/apache-tomcat-8.5.16.tar.gz /opt/tomcat

vim Dockerfile

FROM centos:7
MAINTAINER this is tomcat image <wl>
ADD jdk-8u91-linux-x64.tar.gz /usr/local/
WORKDIR /usr/local/
RUN mv jdk1.8.0_91 /usr/local/java
ENV JAVA_HOME /usr/local/java
ENV JRE_HOME ${JAVA_HOME}/jre
ENV CLASSPATH .:${JAVA_HOME}/lib:${JRE_HOME}/lib
ENV PATH $JAVA_HOME/bin:$PATH
ADD apache-tomcat-8.5.16.tar.gz /usr/local/
WORKDIR /usr/local/
RUN mv apache-tomcat-8.5.16 /usr/local/tomcat
EXPOSE 8080
#CMD ["/usr/local/tomcat/bin/catalina.sh","run"]
ENTRYPOINT ["/usr/local/tomcat/bin/catalina.sh","run"]


//创建新镜像
docker build -t tomcat:centos .

docker run -d --name tomcat01 -p 1216:8080 tomcat:centos 
 
http://192.168.10010:1216

----------------------------mysql镜像------------------------------------
mkdir /opt/mysqld
cd /opt/mysqld

vim Dockerfile

FROM centos:7
MAINTAINER this is mysql image <wl>
RUN yum -y install gcc gcc-c++ ncurses ncurses-devel bison cmake make
RUN useradd -M -s /sbin/nologin  mysql
ADD mysql-boost-5.7.20.tar.gz /usr/local/src/
WORKDIR /usr/local/src/mysql-5.7.20/
RUN cmake \
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
-DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock \
-DSYSCONFDIR=/etc \
-DSYSTEMD_PID_DIR=/usr/local/mysql \
-DDEFAULT_CHARSET=utf8  \
-DDEFAULT_COLLATION=utf8_general_ci \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_ARCHIVE_STORAGE_ENGINE=1 \
-DWITH_BLACKHOLE_STORAGE_ENGINE=1 \
-DWITH_PERFSCHEMA_STORAGE_ENGINE=1 \
-DMYSQL_DATADIR=/usr/local/mysql/data \
-DWITH_BOOST=boost \
-DWITH_SYSTEMD=1 && make && make install
RUN chown -R mysql:mysql /usr/local/mysql/
RUN rm -rf /etc/my.cnf
ADD my.cnf /etc/
RUN chown mysql:mysql /etc/my.cnf
ENV PATH=/usr/local/mysql/bin:/usr/local/mysql/lib:$PATH
WORKDIR /usr/local/mysql/
RUN bin/mysqld \
--initialize-insecure \
--user=mysql \
--basedir=/usr/local/mysql \
--datadir=/usr/local/mysql/data
RUN cp /usr/local/mysql/usr/lib/systemd/system/mysqld.service /usr/lib/systemd/system/
EXPOSE 3306
ADD run.sh /usr/local/src
RUN chmod 755 /usr/local/src/run.sh
RUN sh /usr/local/src/run.sh
#CMD ["/usr/sbin/init"]


vim my.cnf
[client]
port = 3306
default-character-set=utf8
socket = /usr/local/mysql/mysql.sock

[mysql]
port = 3306
default-character-set=utf8
socket = /usr/local/mysql/mysql.sock

[mysqld]
user = mysql
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
port = 3306
character_set_server=utf8
pid-file = /usr/local/mysql/mysqld.pid
socket = /usr/local/mysql/mysql.sock
server-id = 1

sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_AUTO_VALUE_ON_ZERO,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,PIPES_AS_CONCAT,ANSI_QUOTES


vim run.sh
#!/bin/bash
/usr/local/mysql/bin/mysqld    
systemctl enable mysqld


//创建新镜像
docker build -t mysql:centos .

//启动容器,并进行初始化
docker run --name=mysql_server -d -P --privileged mysql:centos /usr/sbin/init

//进容器给权限
docker ps -a
CONTAINER ID   IMAGE          COMMAND             CREATED          STATUS          PORTS                     NAMES
f9a4d8f6c65f   mysql:centos   "/usr/sbin/init"    17 seconds ago   Up 16 seconds   0.0.0.0:49153->3306/tcp   mysql_server

//进入容器,授权远程连接 mysql
docker exec -it f9a4d8f6c65f /bin/bash

mysql -u root -p
grant all privileges on *.* to 'root'@'%' identified by 'abc123';
grant all privileges on *.* to 'root'@'localhost' identified by 'abc123';
flush privileges;

//在客户端连接mysql容器
mysql -h 192.168.100.10 -u root -P 49153 -pabc123
 

————————————————
本文为CSDN博主「淘小欣」的原创文章
原文链接:https://blog.csdn.net/weixin_44621343/article/details/115512659

12-06 07:47