Docker 学习笔记 - 创建镜像文件

Docker创建镜像一般可以分成手动创建和自动创建。手动创建是自动创建的前提,如果手动创建的镜像成功了,那么我们可以通过dockerfile来自动化这一操作。

手动创建

首先看看如何手动创建一个简单的nginx镜像

首先从一个基础镜像 centos:6.9 启动一个容器

[root@ip-172-16-1-150 ec2-user]# docker run -dit centos:6.9
0735b720672ffd0beb6c8c230b5cff97be8db3f458f28972828d8b8b680b3f9b
[root@ip-172-16-1-150 ec2-user]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0735b720672f centos:6.9 "/bin/bash" 3 seconds ago Up 2 seconds awesome_hodgkin

进入容器,然后进行一些操作,安装epel源,安装nginx

[root@ip-172-16-1-150 ec2-user]# docker attach 0735b720672f
[root@0735b720672f /]# yum install epel-release -y
[root@0735b720672f /]# yum install nginx -y

然后创建一个脚本 init.sh

#!/bin/sh service nginx start nginx -g "daemon off;"

然后退出容器,提交commit 为一个镜像

[root@ip-172-16-1-150 ec2-user]# docker commit 0735b720672f centos6.9_nginx:v5
sha256:37d894e100105a6010507ff5aad009d30398fd4e9b7ea10da56597ba57daaf9a

现在来测试一下,注意我的初始命令我强制他执行我自己写的脚本,这样可以保证他一直处于夯住的状态,而不会自动就退出容器, docker ps 命令查看他确实夯住了,没有退出

[root@ip-172-16-1-150 ec2-user]# docker run -d -p 80:80 centos6.9_nginx:v5 /bin/bash init.sh
24121b205614a3c16be4225bec7738f9e00133110e14417ec5ecb560708ab00d
[root@ip-172-16-1-150 ec2-user]# docker ps -a
CONTAINER ID        IMAGE                COMMAND               CREATED             STATUS                      PORTS                NAMES
24121b205614        centos6.9_nginx:v5   "/bin/bash init.sh"   2 seconds ago       Up 2 seconds                0.0.0.0:80->80/tcp   wonderful_chandrasekhar

测试是成功的。

Docker 学习笔记 - 创建镜像文件

自动创建

生产环境中,程序员会经常性地发布新的代码到代码仓库中,比如GitHub,然后我们需要把这些新的代码克隆到我们的容器环境中,提交,我们可以用dockerfile来自动化这个步骤。

dockerfile主要组成部分:
​ 基础镜像信息 FROM centos:6.9
​ 制作镜像操作指令 RUN yum install openssh-server -y
​ 容器启动时执行初始命令 CMD ["/bin/bash"]
dockerfile常用指令:

FROM  指定基础镜像
MAINTAINER 指定维护者信息,可以没有
LABLE      描述,标签, 和MAINTAINER的区别是可以支持多行描述
RUN  在命令前面加上RUN即可
ADD  拷贝文件到容器里面,自动解压tar文件
WORKDIR 设置当前工作目录
VOLUME 设置卷,挂载主机目录
EXPOSE 指定对外的端口(-P 随机端口)
CMD 指定容器启动后的要干的事情(比如shell脚本,容易替换)
dockerfile其他指令: 
COPY 复制文件(不会解压)rootfs.tar.gz
ENV  环境变量
ENTRYPOINT  容器启动后执行的命令(无法被替换,启容器的时候指定的命令,会被当成参数)

下面来看看如何实现上面的步骤

例子1

新建一个文件 dockerfile,输入下面的内容

[root@ip-172-16-1-150 nginx]# cat dockerfile
FROM centos:6.9
RUN yum install -y epel-release
RUN yum install -y nginx
RUN service nginx start
CMD ["nginx","-g","daemon off;"]

然后执行docker image build的操作,注意我的dockerfile里面的RUN操作,每一步都相当于docker run的效果,他会创建一个临时的容器,执行命令,提交成一个临时镜像;然后下一步的RUN会从上一步的临时镜像来生成新的临时容器,执行新的命令,提交成另外一个新的临时镜像,周而复始,直到结束

[root@ip-172-16-1-150 nginx]# docker image build -t centos6.9_nginx:v7 .
Sending build context to Docker daemon  2.048kB
Step 1/5 : FROM centos:6.9
 ---> 2199b8eb8390
Step 2/5 : RUN yum install -y epel-release
 ---> Using cache
 ---> c7f51c27d606
Step 3/5 : RUN yum install -y nginx
 ---> Using cache
 ---> 6e3c1f4b2292
Step 4/5 : RUN service nginx start
 ---> Using cache
 ---> 67d67a63a321
Step 5/5 : CMD ["nginx","-g","daemon off;"]
 ---> Using cache
 ---> 868de8ae31bd
Successfully built 868de8ae31bd
Successfully tagged centos6.9_nginx:v7

最后测试一下, 成功!

Docker 学习笔记 - 创建镜像文件

例子2

下面看另外一个例子,自动安装一个tomcat,然后从宿主机拷贝相关的文件到容器上,并且执行相关的脚本。

首先仍然是创建 dockerfile。 这次我使用了一些新的关键字。

WORKDIR 的作用类似 cd,切换目录,如果直接cd切换目录,他没有改变任何内容,因此下一次的临时容器不会有任何记录;

ADD的作用和COPY相似,都是把宿主机的内容拷贝到容器里面,前者可以自动解压tar文件,后者不行。

EXPOSE 则是开放端口。如果我们启动容器的时候使用了-P命令,他会随机映射一个端口到这个我们指定的端口

FROM centos:6.9
RUN yum install epel-release -y
RUN yum install tomcat -y
WORKDIR /var/lib/tomcat/webapps/
ADD xiaoniao ./xiaoniao
RUN mv xiaoniao ROOT
EXPOSE 8080
ADD init.sh /init.sh
CMD ["/bin/bash","/init.sh"]

下面是一个简单的init.sh脚本,启动服务,确保能夯住


#!/bin/bash

service tomcat start
tail -f /var/log/tomcat/catalina.out

构建一个镜像试试看


[root@ip-172-16-1-150 dockerfile]# docker image build -t test:v1 --network=host .
Sending build context to Docker daemon  437.8kB
Step 1/9 : FROM centos:6.9
 ---> 2199b8eb8390
Step 2/9 : RUN yum install epel-release -y
 ---> Using cache
 ---> d49277d3efe5
Step 3/9 : RUN yum install tomcat -y
 ---> Using cache
 ---> d25017d00000
Step 4/9 : WORKDIR /var/lib/tomcat/webapps/
 ---> Using cache
 ---> 2c1abca7319f
Step 5/9 : ADD xiaoniao ./xiaoniao
 ---> 7dcf2bdeb9a2
Step 6/9 : RUN mv xiaoniao ROOT
 ---> Running in 91a5fb4229c9
Removing intermediate container 91a5fb4229c9
 ---> 592d734b5c15
Step 7/9 : EXPOSE 8080
 ---> Running in e19e4548212a
Removing intermediate container e19e4548212a
 ---> 569d84aed65b
Step 8/9 : ADD init.sh /init.sh
 ---> 5b25e8efdf50
Step 9/9 : CMD ["/bin/bash","/init.sh"]
 ---> Running in 57d39a1e02df
Removing intermediate container 57d39a1e02df
 ---> f51e7c04728c
Successfully built f51e7c04728c
Successfully tagged test:v1

然后启动一个容器


[root@ip-172-16-1-150 dockerfile]# docker run -d -P test:v1
7cfd8aa199d922b99fb54d5db7202a1d3b5fb4492375a0d8329addd4e3af3bbe
[root@ip-172-16-1-150 dockerfile]# docker ps -a
CONTAINER ID        IMAGE                 COMMAND                CREATED             STATUS                        PORTS                     NAMES
7cfd8aa199d9        test:v1               "/bin/bash /init.sh"   4 seconds ago       Up 2 seconds                  0.0.0.0:32773->8080/tcp   romantic_jang

通过随机端口访问看看,成功!

Docker 学习笔记 - 创建镜像文件

例3

我们在上面的基础上再添加一些新的服务,比如说安装一个SSH的远程访问服务,然后配置一个初始的密码,用户启动docker 容器的时候可以自己进行替换

首先修改我们的dockerfile
这次我添加了两个新的关键字 ENV 和 ENTRYPOINT

ENV的作用是创建一个环境变量,ENTRYPOINT 和 CMD 类似,但是当用户手动输入初始命令时,他不会像CMD一样来替换,而是作为参数传给ENTRYPOINT后面跟的命令

WORKDIR /var/lib/tomcat/webapps/
ADD xiaoniao ./xiaoniao
RUN mv xiaoniao ROOT

RUN yum install openssh-server -y

ENV SSH_PWD='12345'
EXPOSE 8080 22
ADD init.sh /init.sh
ENTRYPOINT ["/bin/bash","/init.sh"]

接下来看看init.sh 的配置,这个脚本启动tomcat和sshd的服务,然后做一个判断,如果用户输入的参数不为空,那么把用户输入的值赋值给SSH_PWD这个变量,然后用这个变量的值重置root密码,最后一条命令夯住容器

#!/bin/bash

service tomcat start
service sshd start
if [ ! -z $1 ];then
        SSH_PWD=$1
fi

echo "$SSH_PWD" | passwd --stdin root

tail -f /var/log/tomcat/catalina.out
~                                                   

构建一下镜像

[root@ip-172-16-1-150 dockerfile]# docker image build -t test:v10 .
Sending build context to Docker daemon  437.8kB
Step 1/11 : FROM centos:6.9
 ---> 2199b8eb8390
Step 2/11 : RUN yum install epel-release -y
 ---> Using cache
 ---> d49277d3efe5
Step 3/11 : RUN yum install tomcat -y
 ---> Using cache
 ---> d25017d00000
Step 4/11 : WORKDIR /var/lib/tomcat/webapps/
 ---> Using cache
 ---> 2c1abca7319f
Step 5/11 : ADD xiaoniao ./xiaoniao
 ---> Using cache
 ---> 7dcf2bdeb9a2
Step 6/11 : RUN mv xiaoniao ROOT
 ---> Using cache
 ---> 592d734b5c15
Step 7/11 : RUN yum install openssh-server -y
 ---> Using cache
 ---> ec03f611047c
Step 8/11 : ENV SSH_PWD='12345'
 ---> Using cache
 ---> 2cef62b3c9db
Step 9/11 : EXPOSE 8080 22
 ---> Using cache
 ---> 9926c828d6ad
Step 10/11 : ADD init.sh /init.sh
 ---> Using cache
 ---> 234460473e7e
Step 11/11 : ENTRYPOINT ["/bin/bash","/init.sh"]
 ---> Using cache
 ---> 233721fcbeca
Successfully built 233721fcbeca
Successfully tagged test:v10

运行三个容器试试看,第一个不指定密码,那么root的密码就是默认的;第二个通过ENTRYYPOINT 来传递一个参数来设置密码;第三通过ENV来替换掉环境变量的值


[root@ip-172-16-1-150 dockerfile]# docker run -d --name test1 -P test:v10
5c4755b91d2f55f7596b4ce8e41728c2e9cfe71cd4eda2cdb5442f3d7ae2cd2d

[root@ip-172-16-1-150 dockerfile]# docker run -d --name test2 -P test:v10 abc
c6386941f451008ef39d00ae5cf7b4b6839e672eadb4ee0a5aee45de2108fc81

[root@ip-172-16-1-150 dockerfile]# docker run -d --name test3 --env "SSH_PWD=222" -P test:v10
7b174a5f6798f48fce449d13258f0469bcd806ce42dee0f745cbf728dadd35ce

```[root@ip-172-16-1-150 dockerfile]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7b174a5f6798 test:v10 "/bin/bash /init.sh" 6 seconds ago Up 5 seconds 0.0.0.0:32817->22/tcp, 0.0.0.0:32816->8080/tcp test3
c6386941f451 test:v10 "/bin/bash /init.sh …" 31 seconds ago Up 29 seconds 0.0.0.0:32815->22/tcp, 0.0.0.0:32814->8080/tcp test2
5c4755b91d2f test:v10 "/bin/bash /init.sh" 45 seconds ago Up 43 seconds 0.0.0.0:32813->22/tcp, 0.0.0.0:32812->8080/tcp test1


最后测试一下,注意不同容器的随机不同端口连接,测试是成功的,不同的端口对应的容器我需要用不同的密码才能登陆

[root@ip-172-16-1-150 dockerfile]# ssh [email protected] -p 32817
The authenticity of host '[172.16.1.150]:32817 ([172.16.1.150]:32817)' can't be established.
RSA key fingerprint is SHA256:CJxIwKDEhR33i/FPM7cZ7eulguMcbvSHI2BPyrCaG0c.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[172.16.1.150]:32817' (RSA) to the list of known hosts.
[email protected]'s password:
[root@7b174a5f6798 ~]# exit
logout
Connection to 172.16.1.150 closed.
[root@ip-172-16-1-150 dockerfile]# ssh [email protected] -p 32815
The authenticity of host '[172.16.1.150]:32815 ([172.16.1.150]:32815)' can't be established.
RSA key fingerprint is SHA256:4osfshKtt/5gdxJSH4h4IVPjvM7XPGhFIweMBG206mI.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[172.16.1.150]:32815' (RSA) to the list of known hosts.
[email protected]'s password:
[root@c6386941f451 ~]# exit
logout
Connection to 172.16.1.150 closed.
[root@ip-172-16-1-150 dockerfile]# ssh [email protected] -p 32813
The authenticity of host '[172.16.1.150]:32813 ([172.16.1.150]:32813)' can't be established.
RSA key fingerprint is SHA256:k9IpONHp2yLviPTAVjg6XJeYViWgT5NvQyN4zFIj3Ws.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[172.16.1.150]:32813' (RSA) to the list of known hosts.
[email protected]'s password:
[root@5c4755b91d2f ~]# exit
logout
Connection to 172.16.1.150 closed.
[root@ip-172-16-1-150 dockerfile]#

猜你喜欢

转载自blog.51cto.com/beanxyz/2539724
今日推荐