书籍来源:《CKA/CKAD应试指南:从Docker到Kubernetes完全攻略》
一边学习一边整理老师的课程内容及实验笔记,并与大家分享,侵权即删,谢谢支持!
附上汇总贴:CKA备考实验 | 汇总_热爱编程的通信人的博客-CSDN博客
前面所使用的镜像都是我们从网上下载下来的,有的镜像并不能满足我们的需求,比如centos的镜像里就没有ifconfig命令,所以很多时候我们需要根据自己的需要来自定义镜像。
自定义镜像的过程并非从零到有的过程,而是在已经存在镜像的基础上进行修改,这个已经存在的镜像我们称之为“基镜像”。
要自定义镜像的话就需要写Dockerfile文件了,如果文件名不是Dockerfile的话,那么编译镜像的时候需要使用-f来指定文件名,如图2-1所示。
构建镜像的本质就是,先利用基镜像生成一个临时容器,然后在这个临时容器里执行Dockerfile里指定的命令,等做完所有的操作之后,把这个临时容器导出为一个新的镜像。最后把这个临时容器删除。
关键就是如何写Dockerfile,Dockerfile的格式及常用命令如下。
FROM:指定基镜像。
MAINTAINER:维护者的信息。
RUN:想在临时容器里执行的操作系统命令。
ADD file /path/:把物理机里file拷贝到镜像的指定目录/path。
COPY file /path/:把物理机里file拷贝到镜像的指定目录/path。
ENV:指定变量。
USER:指定容器内部以哪个用户运行进程。
VOLUME:指定数据卷。
EXPOSE:指定镜像容器所使用的端口,这个只是一个标记。
CMD:指定镜像创建出来的容器运行什么进程。
练习1:创建可以执行ifconfig的centos镜像
Dockerfile内容如下。
##########实操验证##########
[root@vms100 ~]# cat Dockerfile
FROM hub.c.163.com/library/centos
MAINTAINER duan
RUN yum install net-tools -y
CMD ["/bin/bash"]
[root@vms100 ~]#
这个文件里指明了基于
http://hub.c.163.com/library/centos这个镜像自定义新的镜像,在新的镜像里安装net-tools工具包。
在临时容器执行系统命令的时候都要以RUN开头,建语法如下。
docker build -t 新镜像名:tag .,这里的“.”表示的是当前目录。如果构建镜像的文件名不是Dockerfile的话,需要使用-f指定文件名,如下:
docker build -t 新镜像名:tag . -f file
开始构建。
##########实操验证##########
[root@vms100 ~]# docker build -t centos:v1 .
[+] Building 13.3s (6/6) FINISHED
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 193B 0.0s
=> [internal] load metadata for hub.c.163.com/library/centos:latest 0.0s
=> [1/2] FROM hub.c.163.com/library/centos 0.0s
=> [2/2] RUN yum install net-tools -y 12.3s
=> exporting to image 1.0s
=> => exporting layers 1.0s
=> => writing image sha256:09a13e02d80a1f9082c04d8672b10251762d7c565a8d3922ff40714ef8e6c014 0.0s
=> => naming to docker.io/library/centos:v1 0.0s
[root@vms100 ~]#
构建完成,查看现有镜像。
##########实操验证##########
[root@vms100 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos v1 09a13e02d80a 40 seconds ago 392MB
nginx latest 605c77e624dd 16 months ago 141MB
hub.c.163.com/library/wordpress latest dccaeccfba36 5 years ago 406MB
hub.c.163.com/library/centos latest 328edcd84f1b 5 years ago 193MB
hub.c.163.com/library/mysql latest 9e64176cd8a2 6 years ago 407MB
[root@vms100 ~]#
使用该镜像创建出一个容器,验证是否可以使用ifconfig命令。
##########实操验证##########
[root@vms100 ~]# docker run --rm -it centos:v1
[root@60c51a993bc0 /]# ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 6 bytes 508 (508.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@60c51a993bc0 /]# exit
exit
[root@vms100 ~]#
可以看到一切是正常的。
练习2:自定义nginx镜像
先做准备工作,所需要的repo文件拷贝出来。
##########实操验证##########
[root@vms100 ~]# cd /etc/yum.repos.d/
[root@vms100 yum.repos.d]# tar zcf /root/repo.tar.gz *
[root@vms100 yum.repos.d]# cd
[root@vms100 ~]#
这里把物理机/etc/yum.repos.d里的repo文件放在压缩文件repo.tar.gz里了。
物理机目录/etc/yum.repos.d/里的这些repo文件是在一开始安装docker时就下载下来的。
创建index.html内容如下。
##########实操验证##########
[root@vms100 ~]# cat index.html
test11
[root@vms100 ~]#
写dockerfile1,内容如下。
##########实操验证##########
[root@vms100 ~]# cat dockerfile1
FROM hub.c.163.com/library/centos
MAINTAINER duan
# 清除自带的yum源文件
RUN rm -rf /etc/yum.repos.d/*
# 把打包好的repo文件拷贝到/etc/yum.repos.d里,为新的yum
ADD repo.tar.gz /etc/yum.repos.d/
RUN yum install -y nginx
# 把nginx默认主页文件拷贝进去
ADD index.html /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off; "]
[root@vms100 ~]#
注意1:centos自带的yum源里并没有nginx软件包,所以在执行yum install nginx -y之前需要配置yum源,这里把打包好的repo文件拷贝到镜像的/etc/yum.repos.d里。
注意2:在容器里nginx作为守护进程运行的话,必须要以nginx -g daemon off这个格式运行,这个格式是固定的。
注意3:一定要注意拷贝yum源,安装,再拷贝index.html的顺序,考虑下为什么。
开始构建,指定镜像的名字为nginx:v1。
##########实操验证##########
[root@vms100 ~]# docker build -t nginx:v1 . -f dockerfile1
[+] Building 29.6s (10/10) FINISHED
=> [internal] load build definition from dockerfile1 0.0s
=> => transferring dockerfile: 464B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for hub.c.163.com/library/centos:latest 0.0s
=> CACHED [1/5] FROM hub.c.163.com/library/centos 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 1.53kB 0.0s
=> [2/5] RUN rm -rf /etc/yum.repos.d/* 0.3s
=> [3/5] ADD repo.tar.gz /etc/yum.repos.d/ 0.1s
=> [4/5] RUN yum install -y nginx 27.7s
=> [5/5] ADD index.html /usr/share/nginx/html 0.0s
=> exporting to image 1.4s
=> => exporting layers 1.4s
=> => writing image sha256:023db094d7a5564fc2cf8eac45ff2743b07e1b56f5df0688d9f994bcf7203132 0.0s
=> => naming to docker.io/library/nginx:v1 0.0s
[root@vms100 ~]#
因为文件名是dockerfile1,不是Dockerfile,以这里需要-f来指定。
使用此镜像运行一个容器,并验证。
##########实操验证##########
[root@vms100 ~]# docker run -d --name=web --restart=always -p 80:80 nginx:v1
41b77eb2855d6128d20fe0a863e2a7907442d49fa7b02a79b9ad033cc9778e9a
[root@vms100 ~]#
在浏览器里打开192.168.26.100,查看结果,如图2-2所示。
有的读者会问,如何修改nginx的配置文件?其实只要把配置文件修改好,以ADD的方式添加过去即可。
自行删除web容器。
练习3:验证ADD和COPY的区别
ADD和COPY都可以把当前目录里的文件拷贝到临时容器里,是ADD和COPY在拷贝压缩文件的时候存在一些区别。ADD把压缩文件拷贝到临时容器里时会自动解压,COPY不带解压功能。
在当前目录随意创建一个压缩文件,这里有个aa.tar.gz,内容如下。
##########实操验证##########
[root@vms100 ~]# tar zcvf aa.tar.gz epel.repo index.html
epel.repo
index.html
[root@vms100 ~]# tar ztf aa.tar.gz
epel.repo
index.html
[root@vms100 ~]#
创建dockerfile2,内容如下。
##########实操验证##########
[root@vms100 ~]# cat dockerfile2
FROM hub.c.163.com/library/centos
MAINTAINER duan
# 在临时容器里创建目录/11和/22
RUN mkdir /11 /22
# 利用ADD把aa.tar.gz拷贝到/11里,利用COPY把aa.tar.gz拷贝到/22里
ADD aa.tar.gz /11
COPY aa.tar.gz /22
CMD ["/bin/bash"]
[root@vms100 ~]#
aa.tar.gz以ADD的方式拷贝到镜像的/11目录。
aa.tar.gz以COPY的方式拷贝到镜像的/22目录。
编译镜像,镜像名为centos:add-copy。
##########实操验证##########
[root@vms100 ~]# docker build -t centos:add-copy . -f dockerfile2
[+] Building 0.6s (9/9) FINISHED
=> [internal] load build definition from dockerfile2 0.0s
=> => transferring dockerfile: 343B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for hub.c.163.com/library/centos:latest 0.0s
=> CACHED [1/4] FROM hub.c.163.com/library/centos 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 526B 0.0s
=> [2/4] RUN mkdir /11 /22 0.3s
=> [3/4] ADD aa.tar.gz /11 0.1s
=> [4/4] COPY aa.tar.gz /22 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:1d95866ca515c62260cee26cf2023ce73bd59a2f50972e11b948ea02b534be0a 0.0s
=> => naming to docker.io/library/centos:add-copy 0.0s
[root@vms100 ~]#
使用该镜像创建出容器验证结果。
##########实操验证##########
[root@vms100 ~]# docker run --rm -it centos:add-copy
[root@826661c133c4 /]# ls /11
epel.repo index.html
[root@826661c133c4 /]# ls /22
aa.tar.gz
[root@826661c133c4 /]# exit
exit
[root@vms100 ~]#
可以看到,以ADD方式拷贝过去的压缩文件进行了解压操作,而以COPY方式拷贝过去的并没有解压。
练习4:USER命令的使用
前面做的镜像里,都是以root来运行进程,如果要以指定的用户来运行进程,可以使用USER命令,创建dockerfile3,内容如下。
##########实操验证##########
[root@vms100 ~]# cat dockerfile3
FROM hub.c.163.com/library/centos
MAINTAINER duan
RUN useradd lduan
USER lduan
CMD ["/bin/bash"]
[root@vms100 ~]#
这里首先创建出lduan用户,然后用USER指定后面容器里要以lduan来运行进程。
编译镜像,镜像为centos:user。
##########实操验证##########
[root@vms100 ~]# docker build -t centos:user . -f dockerfile3
[+] Building 0.4s (6/6) FINISHED
=> [internal] load build definition from dockerfile3 0.0s
=> => transferring dockerfile: 194B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for hub.c.163.com/library/centos:latest 0.0s
=> CACHED [1/2] FROM hub.c.163.com/library/centos 0.0s
=> [2/2] RUN useradd lduan 0.3s
=> exporting to image 0.1s
=> => exporting layers 0.0s
=> => writing image sha256:af8135401b6e99c34b5fde0e63dde5ff6bd931cdd596e18cf8729c2164e4eded 0.0s
=> => naming to docker.io/library/centos:user 0.0s
[root@vms100 ~]#
使用该镜像创建容器。
##########实操验证##########
[root@vms100 ~]# docker run --restart=always --name=c1 -it centos:user
[lduan@b63a47b92330 /]$
[lduan@b63a47b92330 /]$ whoami
lduan
[lduan@b63a47b92330 /]$ exit
exit
You have new mail in /var/spool/mail/root
[root@vms100 ~]#
可以看到容器里的进程是以lduan的身份来运行的。如果要以root身份进入容器里的话,加上--user-root选项即可。
##########实操验证##########
[root@vms100 ~]# docker exec -it --user=root c1 bash
[root@b63a47b92330 /]#
[root@b63a47b92330 /]# whoami
root
[root@b63a47b92330 /]# exit
exit
[root@vms100 ~]#
删除这个容器c1。
##########实操验证##########
[root@vms100 ~]# docker rm -f c1
c1
[root@vms100 ~]#
练习5:用ENV来指定变量
创建dockerfile4。
##########实操验证##########
[root@vms100 ~]# cat dockerfile4
FROM hub.c.163.com/library/centos
MAINTAINER duan
ENV myenv=/aa
CMD ["/bin/bash"]
[root@vms100 ~]#
构建镜像名字为centos:env。
##########实操验证##########
[root@vms100 ~]# docker build -t centos:env . -f dockerfile4
[+] Building 0.0s (5/5) FINISHED
=> [internal] load build definition from dockerfile4 0.0s
=> => transferring dockerfile: 179B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for hub.c.163.com/library/centos:latest 0.0s
=> CACHED [1/1] FROM hub.c.163.com/library/centos 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:cb01093b4b3efb6f2dd6601bf382bc44f8d7188ee42c33be9ea941a120bc1af3 0.0s
=> => naming to docker.io/library/centos:env 0.0s
[root@vms100 ~]#
使用该镜像创建出来一个容器。
##########实操验证##########
[root@vms100 ~]# docker run --rm -it centos:env
[root@1fe0457c0cc9 /]# echo $myenv
/aa
[root@1fe0457c0cc9 /]# exit
exit
[root@vms100 ~]#
可以看到容器里存在一个变量myenv=aa。
在创建容器的时候是可以使用-e来指定变量的值的。
##########实操验证##########
[root@vms100 ~]# docker run --rm -it -e myenv=xxx centos:env
[root@4962c57a84f8 /]# echo $myenv
xxx
[root@4962c57a84f8 /]# exit
exit
[root@vms100 ~]#
练习6:数据卷
创建dockerfile5。
##########实操验证##########
[root@vms100 ~]# cat dockerfile5
FROM hub.c.163.com/library/centos
MAINTAINER duan
VOLUME ["/data1"]
CMD ["/bin/bash"]
[root@vms100 ~]#
此新镜像创建出来的容器里,会创建一个目录/data1绑定物理机的随机目录。
构建镜像,名字为centos:volume。
##########实操验证##########
[root@vms100 ~]# docker build -t centos:volume . -f dockerfile5
[+] Building 0.1s (5/5) FINISHED
=> [internal] load build definition from dockerfile5 0.0s
=> => transferring dockerfile: 183B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for hub.c.163.com/library/centos:latest 0.0s
=> CACHED [1/1] FROM hub.c.163.com/library/centos 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:95dfdabf2cd5c7a037a5da91ef4febbcb6e4c394dc8d7058b5e248b98b8cf386 0.0s
=> => naming to docker.io/library/centos:volume 0.0s
You have new mail in /var/spool/mail/root
[root@vms100 ~]#
使用此镜像创建一个容器出来。
##########实操验证##########
[root@vms100 ~]# docker run --rm -it centos:volume
[root@c20909268773 /]# ls /data1/
[root@c20909268773 /]#
在其他终端查看此容器的属性。
##########实操验证##########
[root@vms100 ~]# docker inspect c20909268773 | grep -A5 Mounts
"Mounts": [
{
"Type": "volume",
"Name": "a75ed99632595b2bd0da5c36ffcd8a4336b284825fa3f92f4da9df48590085af",
"Source": "/var/lib/docker/volumes/a75ed99632595b2bd0da5c36ffcd8a4336b284825fa3f92f4da9df48590085af/_data",
"Destination": "/data1",
[root@vms100 ~]#
注意:如果想有多个挂载点的话,应该写成VOLUME["/data1","/data"] 。
作业:创建可以ssh的centos
dockerfile内容如下。
FROM centos:v1
MAINTAINER duan
RUN rm -rf /etc/yum.repos.d/*
ADD epel.repo /etc/yum.repos.d/
ADD CentOS-Base.repo /etc/yum.repos.d/
RUN yum install openssh-clients openssh-server -y
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key && ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key && ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key
RUN sed -i '/UseDNS/cUseDNS no' /etc/ssh/sshd_config
RUN echo "root:redhat" | chpasswd
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
更好的写法:
FROM centos:v1
MAINTAINER duan
RUN rm -rf /etc/yum.repos.d/*
ADD repo.tar.gz /etc/yum.repos.d/
RUN yum install openssh-clients openssh-server -y && \
ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key && \
ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key && \
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key && \
sed -i '/UseDNS/cUseDNS no' /etc/ssh/sshd_config && \
echo "root:redhat" | chpasswd
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]