在微服务的时代学会使用Docker是必须的,在Docker里面应用是部署在容器(Container)里的,而创建容器就需要镜像(Image),得到镜像的方法有两种。一种是通过拉取centos基础镜像,在里面进行安装配置,最后打包成新的镜像使用;另外一种就是直接在Docker云里拉取人家安装配置好的镜像,然后通过Dockerfile把自己的配置参数加入进去,最后打包成新的镜像使用。
相比之下,第二种方法更加简单,因为知识我们不需要去找应用的官网,下载合适的版本,安装各种依赖库,安装各种辅助工具,解决各种兼容问题了,只需要考虑我们该考虑的问题即可!
今天福哥将带着大家学习如何使用Dockerfile创建Docker镜像,大家跟着来吧!
要注意一个问题,我们选择第二种方式创建镜像是基于我们要搭建微服务的,如果你喜欢在一个容器里面安装各种各样的应用的话,那么还是采用第一种方式吧。
前面说过了,第二种方法是在别人的安装配置好的镜像基础之上进行参数调整的,所以首先我们得知道如何找到别人安装配置好的镜像。
在Docker云里面有着无数多的大神弄好的镜像,我们可以通过search命令进行搜索,基本上我们想要的应用都可以找到不止一个基础镜像。例如:我们想安装一个nginx服务,就可以执行下面的命令搜索。
docker search nginx

注意INDEX列和NAME列,INDEX为docker.io的就是官方镜像库,NAME就是完整的镜像地址。选择好了基础镜像之后就可以通过“pull”命令拉取下来了。例如:福哥拉取了“docker.io/nginx”这个镜像。
docker pull docker.io/nginx
不过,我们今天要学习的是通过Dockerfile来创建镜像,也就是说我们不需要单独地拉取镜像下来,这些都会在后面的Dockerfile脚本里面自动完成的了。
其实Dockerfile就是一个脚本,Docker会根据我们编写的Dockerfile脚本完成一系列的自动部署操作,最后将最终的状态生成一个镜像。
FROM命令用来指定基础镜像,我们不能凭空建立一个系统环境,需要在某个已经存在的镜像基础之上创建新的镜像。
FROM docker.io/nginx
RUN命令可以执行Shell命令,我们可以通过Shell命令完成我们想要的部署操作。
RUN yum install wget
MAINTAINER命令用来设置作者的信息。
MAINTAINER Andy Bogate <tongfu@tongfu.net>
ADD命令可以将本地的文件打包到镜像里面,支持通配符。
如果需要把目录打包到镜像里面,可以先将目录打包到一个tar压缩包里面,然后添加这个压缩包。
ADD tfums_server.conf /etc/nginx/conf.d/
COPY命令可以将本地的文件打包到镜像里面,不会对tar压缩包进行解压缩。
COPY tfphp-1.0.0-utf-8.tar /data/web/download/
CMD命令指定的命令会在容器启动时候执行,类似rc.local的作用,但是更好用。
CMD /etc/start_service.sh
ENTRYPOINT命令就是运行容器的时候第一次要执行的命令,一个Dockerfile里面只能有一个ENTRYPOINT命令,设置了多个的话最后一个生效。
ENTRYPOINT /etc/start_service.sh
LABEL命令可以为镜像添加元数据。
LABEL name="福哥" age="35"
ENV命令可以为镜像添加环境变量,变量在创建镜像的时候,或者镜像被用来启动容器后都是有效的。
可以在docker run时候通过-e设置ENV环境变量。
可以在docker-compose的environment里设置ENV环境变量。
设置两个环境变量id和name。
ENV id 35 ENV name 福哥
在Dockerfile里面设置启用脚本为/root/start.sh,在/root/start.sh里面调用环境变量id和name。
Dockerfile
ENTRYPOINT ["/root/start.sh"]
/root/start.sh
#!/bin/sh
echo "name: ${name}" > /etc/userinfo/$idEXPOSE命令用来指定容器暴露出去的端口。
EXPOSE 80
VOLUME命令用来指定持久化目录。
VOLUME /var/log/mysql
WORKDIR命令用来在Dockerfile执行期间切换“当前目录”使用。镜像被用来启动容器后会切换到WORKDIR目录下面。
WORKDIR /etc/nginx/conf.d/
USER命令用来指定容器的用户。
USER webadmin
ARG命令用来设置创建镜像时候的参数。
ARG参数只在创建镜像的过程中有效,且不能通过外部环境传入。
设置ARG参数。
ARG id=35 ARG name=福哥
引用ARG参数。
RUN echo "name: ${name}" > /tmp/userinfo/$idONBUILD命令可以在别人用我们创建的新镜像去二次创建镜像的时候自动触发执行的命令。
ONBUILD RUN rm -f /etc/.secret_key
编辑好Dockerfile脚本,就可以通过如下的命令创建我们想要的镜像了。
通过“-f”参数指定Dockerfile路径
通过“-t”参数设置新的镜像的名称
最后是创建新的镜像的根目录,根目录下面的内容会被发送到Docker云,要特别注意一下哦~~
docker build -f Dockerfile -t tfums_nginx ./
现在我们打包一个基于docker.io/nginx的镜像,把里面的默认配置文件替换掉。
我们如果都不知道基础镜像的系统结构,就不用谈去修改它了。所以,先拉取基础镜像下来,启动一个临时容器,切进去看看。
[root@dev ~]# docker run -tid --name tfums_nginx -h tfums_nginx --net bridge2 --ip 10.16.1.100 docker.io/nginx 2eb122a5d394f21db69ba478cb2cd57071ce1891654d237f780310aaa342902e
[root@dev ~]# docker exec -it tfums_nginx "/bin/bash"
root@tfums_nginx:/# find / -iname "*nginx*" /etc/rc5.d/S01nginx /etc/rc6.d/K01nginx /etc/logrotate.d/nginx /etc/init.d/nginx-debug /etc/init.d/nginx /etc/default/nginx-debug /etc/default/nginx /etc/systemd/system/multi-user.target.wants/nginx.service /etc/rc0.d/K01nginx /etc/rc1.d/K01nginx /etc/rc2.d/S01nginx /etc/rc3.d/S01nginx /etc/rc4.d/S01nginx /etc/nginx /etc/nginx/nginx.conf /usr/lib/nginx /usr/sbin/nginx-debug /usr/sbin/nginx /usr/share/doc/nginx-module-xslt /usr/share/doc/nginx-module-geoip /usr/share/doc/nginx-module-image-filter /usr/share/doc/nginx /usr/share/doc/nginx-module-njs /usr/share/nginx /var/lib/dpkg/info/nginx-module-image-filter.list /var/lib/dpkg/info/nginx-module-image-filter.md5sums /var/lib/dpkg/info/nginx.postinst /var/lib/dpkg/info/nginx-module-geoip.list /var/lib/dpkg/info/nginx.md5sums /var/lib/dpkg/info/nginx-module-njs.list /var/lib/dpkg/info/nginx-module-njs.postinst /var/lib/dpkg/info/nginx-module-image-filter.postinst /var/lib/dpkg/info/nginx-module-geoip.postinst /var/lib/dpkg/info/nginx-module-xslt.list /var/lib/dpkg/info/nginx-module-njs.md5sums /var/lib/dpkg/info/nginx.list /var/lib/dpkg/info/nginx-module-xslt.md5sums /var/lib/dpkg/info/nginx-module-xslt.postinst /var/lib/dpkg/info/nginx.postrm /var/lib/dpkg/info/nginx.prerm /var/lib/dpkg/info/nginx-module-geoip.md5sums /var/lib/dpkg/info/nginx.preinst /var/lib/dpkg/info/nginx.conffiles /var/lib/systemd/deb-systemd-helper-enabled/multi-user.target.wants/nginx.service /var/lib/systemd/deb-systemd-helper-enabled/nginx.service.dsh-also /var/lib/systemd/deb-systemd-helper-enabled/nginx-debug.service.dsh-also /var/cache/nginx /var/log/nginx /lib/systemd/system/nginx.service /lib/systemd/system/nginx-debug.service /run/nginx.pid find: '/proc/1/map_files': Operation not permitted find: '/proc/30/map_files': Operation not permitted find: '/proc/31/map_files': Operation not permitted find: '/proc/36/map_files': Operation not permitted
可以看到我们搜索到了几个比较重要的内容,包括配置文件和启动脚本,这里面我们只需要替换配置文件即可。
/etc/nginx/nginx.conf
打开nginx.conf,发现真正的配置文件都在/etc/nginx/conf.d/下面。
root@tfums_nginx:/# cat /etc/nginx/nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}查看/etc/nginx/conf.d/目录,发现了唯一的默认配置文件default.conf,打开它看看。
root@tfums_nginx:/# ls /etc/nginx/conf.d/
default.conf
root@tfums_nginx:/# cat /etc/nginx/conf.d/default.conf
server {
listen 80;
listen [::]:80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}在default.conf里是一个标准的nginx的server配置,没什么好说的了,反正等下福哥要替换它。
root@tfums_nginx:/# exit exit
[root@dev ~]# docker stop tfums_nginx tfums_nginx [root@dev ~]# docker rm tfums_nginx tfums_nginx
现在我们开始编写Dockerfile脚本,基础镜像自然就是docker.io/nginx了。首先需要建立一个空目录,把新镜像需要的文件都放里面。
福哥把Docker的镜像都放到了/docker.images下面了,而tfums_nginx是福哥给新的镜像起的名字。
[root@dev /]# cd /docker.images/ [root@dev docker.images]# mkdir tfums_nginx [root@dev docker.images]# cd tfums_nginx/ [root@dev tfums_nginx]#
大家可以看到,我将nignx的80端口上面的服务代理给同福网官网了。
[root@dev tfums_nginx]# cat tfums_server.conf
server {
listen 80;
server_name localhost;
location / {
proxy_pass https://tongfu.net;
proxy_set_header Host tongfu.net;
proxy_set_header X-Real-Ip $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
}
}脚本很简单,说明一下:
基于docker.io/nginx镜像创建
复制tfums_server.conf到nginx配置文件目录下面
删除默认的nginx配置文件。
[root@dev tfums_nginx]# cat Dockerfile FROM docker.io/nginx ADD tfums_server.conf /etc/nginx/conf.d/ RUN rm -f /etc/nginx/conf.d/default.conf
使用build命令创建新的镜像,可以看到每一步都很清晰明白的运行了。
[root@dev tfums_nginx]# docker build -f Dockerfile -t tfums_nginx ./ Sending build context to Docker daemon 3.072 kB Step 1/3 : FROM docker.io/nginx ---> 62d49f9bab67 Step 2/3 : ADD tfums_server.conf /etc/nginx/conf.d/ ---> acd156efa1ce Removing intermediate container 8249905578d5 Step 3/3 : RUN rm -f /etc/nginx/conf.d/default.conf ---> Running in 05fe00f656b2 ---> c48e2f8da850 Removing intermediate container 05fe00f656b2 Successfully built c48e2f8da850
使用新的镜像tfums_nginx创建容器。
[root@dev tfums_nginx]# docker run -tid --name tfums_nginx -h tfums_nginx --net bridge2 --ip 10.16.1.100 tfums_nginx 7e48b13e64a9117e8dddf384124c6644bb2b52d2f747dd68097c8ddca63f1d7e
可以看到容器里面的nginx正在按照福哥的设计将同福网的官网首页代理过来了。

官方提供了一个网站,类似github那样的功能(连界面都基本一样),可以在上面搜索比较好的基础镜像。
DockerHub的官网地址。
这是一个搜索示例,很明显要比search命令强大太多太多了。

今天童鞋们跟着福哥学会了如何使用Dockerfile创建镜像的方法,这其实是最简单的。如何把我们的传统网站或者平台拆分成若干的微服务还是需要比较经验老道的高手进行架构设计的,这个东西福哥会在后面带着大家对实现微服务架构的部署进行一个了解和学习的,敬请期待~~