本期目标:基于Centos7.6,打包一个开箱即用的镜像,可用于运行php项目本文不讨论dockerfile语法,假设你了解基本的类unix操作系统常识,并有一个类unix的运行环境(包括但不限于安装了mac或linux的物理机,类unix虚拟机机器,安装了MinGW或CygWin的windows机器),并且您了解基本的docker操作并具有一定的阅读dockerfiles的能力。准备工作创建一个工作目录mkdir~/docker-learncd~/docker-learn创建一个DockerfiletouchDockerfile然后将你常用的nginx.conf复制到工作目录下cpxxx/nginx.confnginx.conf封装基础镜像编辑我们创建的Dockerfile基本内容声明本镜像继承自最新版centosFROMcentosinstallnginx创建nginx源文件由于centos仓库中没有nginx,所以我们只好更新添加nginx的源到docker复制RHEL源的内容在nginx.org到nginx.repo文件。也可以在本地执行以下命令创建nginx.reposudotee./nginx.repo<<-'EOF'[nginx-stable]name=nginxstablerepobaseurl=http://nginx.org/packages/centos/$releasever/$basearch/gpgcheck=1enabled=1gpgkey=https://nginx.org/keys/nginx_signing.key[nginx-mainline]name=nginxmainlinerepobaseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/gpgcheck=1enabled=0gpgkey=https://nginx.org/keys/nginx_signing.keyEOF写入并复制nginx.repo指令到docker镜像COPYnginx.repo/etc/yum.repos.d/nginx.repo使用yum安装nginx并设置为开机RUNyummakecache&&yuminstallnginx&&chkconfignginx安装phpcentos。默认源有低版本的php和相关包。我们需要更改为具有更新版本的源。本文remi开源镜像安装remi源RUNrpm-ivhhttp://rpms.famillecollet.com/enterprise/remi-release-7.rpm&&yumupdate-y使用yum安装php及相关包并设置开机运行yuminstall-y--enablerepo=remi--enablerepo=remi-php72phpphp-opensslphp-curlphp-bcmathphp-develphp-mbstringphp-mcryptphp-mysqlndphp-pdophp-gdphp-xmlphp-opcachephp-fpm&&chkconfigphp-fpmonCleanupwork众所周知,如果要push到线上,镜像越小越好嘛,dockeryum的运行会产生很多缓存,所以很有必要为我们做一些清理工作RUNyumcleanheaders&&yumcleanpackages&&yumcleanmetadata&&rm-rf/usr/share/man声明了镜像运行时的??入口点,即容器运行时执行的第一个命令。如果不是init,很有可能无法运行某些特权命令。例如,chkconfigENTRYPOINT["/sbin/init"]合并dockerfiledockerfile中的每条指令都会单独生成一层image,这样必然会增加我们image的体积。通常的做法是尽可能将多条指令合并为一条指令,这样可以有效减小图像尺寸。FROMcentos#复制两个repoCOPYconf/tsinghua-base.repo/etc/yum.repos.d/CentOS-Base.repoCOPYconf/nginx.repo/etc/yum.repos.d/nginx.repo#安装组件及相关包运行yummakecache&&yum-yinstallnginx&&chkconfignginxon&&yuminstall-yepel-release&&rpm-ivhhttp://rpms.famillecollet.com/enterprise/remi-release-7.rpm&&yumupdate-y&&yuminstall-y--enablerepo=remi--enablerepo=remi-php72phpphp-opensslphp-curlphp-bcmathphp-develphp-mbstringphp-mcryptphp-mysqlndphp-pdophp-gdphp-xmlphp-opcachephp-fpm&&chkconfigphp-fpmon&&yumcleanheaders&&yumcleanpackages&&yumcleanmetadata&&rm-rf/usr/share/man#declareentrypointENTRYPOINT["/sbin/init"]测试镜像可用性构建镜像价值注意到nginx官方repo不是很稳定当然,在操作过程中可能会出现错误,重试几次后一般都能成功。如果是其他类型的错误,则检查环境和dockerfile是否有问题。泊坞窗构建。-tfirst-build以特权启动后台运行容器,将返回一个ID。使用--privileged选项后,容器将拥有真正的root权限,否则将只有本地普通用户权限。只有在容器中执行一些特殊操作(比如systemctl)时才需要这个选项|grep'[nginx|php]'如果返回结果类似这样,那么我们的操作是正确的>dockerexec-itcca6psaux|grep'[nginx|php]'root10.00.0431124888吗?Ss09:150:00/sbin/initroot170.00.0390966476?Ss09:150:00/usr/lib/systemroot290.10.0351003308?Ss09:150:00/usr/lib/systemroot3700.00.137158821424?Ss09:150:00php-fpm:masterroot3810.00.0242642784?Ss09:150:00/usr/lib/systemdbus3860.00.0580004164?Ss09:150:00/usr/bin/dbus-droot4180.00.046432980?Ss09:150:00nginx:主pnginx4210.00.0468323512?S09:150:00nginx:workerproot5640.00.080961820tty1Ss+09:150:00/sbin/agetty--apache8220.00.037158812468?S09:05php-fpm:池wapache8250.00.037158812468?S09:150:00php-fpm:poolwroot28590.00.0517523448pts/0Rs+09:210:00psaux启动镜像,然后在本地浏览器Console甚至可以看到nginx默认的欢迎页面,https://cr.console.aliyun.com/cn-zhangjiakou/instances/repositories 界面是这样的。使用镜像加速器点击左下角的镜像加速器https://cr.console.aliyun。com/cn-zhangjiakou/instances/mirrors,你会看到你的专属加速链接,找到你的操作系统,一一执行。本文使用Ubuntu版本。可以看到执行的很顺利,没有任何异常。登录阿里云docker仓库sudodockerlogin--username=你的阿里云用户名registry.cn-zhangjiakou.aliyuncs.com密码:你的阿里云密码登录成功创建命名空间点击左侧命名空间,点击创建命名空间,输入你的命名空间。命名空间可以理解为镜像所属的组织。例如:centos镜像的全称是docker.io/centos,docker.io是centos镜像的命名空间,但是docker.io命名空间下centos的镜像不止一张。公有和私有是指镜像在阿里云镜像市场是否可以被公众查看,是否可以在没有任何权限的情况下拉取创建仓库。刚才我们已经创建了命名空间,接下来就是创建仓库了。仓库可以理解为一个组织创建的软件包的名称。比如centos镜像的全称是docker.io/centos,centos是docker.io的一个仓库(软件)。同时centos软件可以有很多版本。进入https://cr.console.aliyun.com/cn-zhangjiakou/instances/repositories仓库页面,点击新建仓库。选择刚刚创建的命名空间,summary就是imageprofile。点击Next,选择本地仓库作为代码源,点击CreateMirrorWarehouse,会发现页面出现一行数据,说明创建成功。将鼠标放在与下载相同的图标上,即可看到专属仓库地址。修改镜像名称。我们需要将刚刚构建的名为first-build的镜像推送到阿里云仓库中。首先,我们使用dockerimages|grepfirst-build找到它的图像ID。接下来我们修改镜像的名称,使其符合docker第三方仓库的镜像名称格式。第三方镜像仓库镜像名称格式:仓库地址/组织/镜像名称:镜像版本号以阿里云为例:阿里云仓库地址/命名空间/仓库名称:版本registry.cn-zhangjiakou.aliyuncs.com/leasn-docker/learn-docker:1然后执行如下命令修改:dockertag3482e8529a90registry.cn-zhangjiakou.aliyuncs.com/leasn-docker/learn-docker:1使用docker镜像|再次grepfirst-build,发现已经找不到了。因为改了名字Pushimagesudodockerpushregistry.cn-zhangjiakou.aliyuncs.com/leasn-docker/learn-dockerPushing全部跑完后,我们会发现阿里云仓库多了一个版本。至此,镜像推送成功。基于阿里云的支持,我们可以在全球范围内使用我们的镜像。为了向为开源事业无私奉献的阿里云致敬。封装项目运行镜像。现在我们要研究如何让镜像运行我们自己的项目。这次可以推送基于我们的阿里云镜像。FROMregistry.cn-zhangjiakou.aliyuncs.com/learn-docker/learn-docker:1将我们准备好的nginx.conf复制到镜像中COPYnginx.conf/etc/nginx/conf/nginx.confnginx.conf全文用户nginx;worker_processesauto;pid/run/nginx.pid;events{worker_connections1024;}http{server{listen80;服务器名称127.0.0.1;根/var/www/html;索引index.php;位置~\.php($|/){fastcgi_pass127.0.0.1:9000;fastcgi_indexindex.php;fastcgi_split_path_info^(.+\.php)(.*)$;fastcgi_paramPATH_INFO$fastcgi_path_info;fastcgi_paramSCRIPT_FILENAME$document_root$fastcgi_script_name;包括fastcgi_params;project,假设我们的项目只有一个文件,位于./proj将我们的项目复制到镜像中,为运行目录加权COPYproj/var/www/htmlRUNchmod-R755/var/www/html/Dockerfile全文FROMregistry.cn-zhangjiakou.aliyuncs.com/leasn-docker/learn-docker:1COPYnginx.conf/etc/nginx/nginx.confCOPYproj/var/www/htmlRUNchmod-R755/var/www/html/构建镜像并使用端口映射运行我们的容器dockerbuild.dockerrun--privileged-d-p8080:80773ed8872493如果不出意外的话,我们已经可以在本地127.0.0.1:8080看到phpinfo()了 现在phpinfo已经看到了,我如何让整个项目跑起来就不细说了。值得一提的是,使用docker-compose推送新版本来编排镜像Compose是一个用于定义和运行多容器Docker应用程序的工具使用Compose,您可以使用YAML文件来配置应用程序的服务。然后,使用一个命令,您可以从配置中创建和启动所有服务。应用安装使用sudoaptinstalldocker-compose调整目录结构在我们当前工作目录之外再添加一个目录,大致是:workingdirectory>docker-learn(Previousworkingdirectory)&&docker-compose.yaml目录树结构:editdocker-compose.yamldocker-compose包含多条指令,使用yaml语言编写。可以理解为把我们在命令行运行的run命令的参数写到一个文件中,然后通过统一的工具配合启动。主要命令:version版本信息,不知道为什么一定是3version:3services需要整理的服务列表,这次我们主要写一个服务叫docker-learnservices:docker-compose.yaml全文版:'3'services:#服务名称docker-learn:#服务是否以特权启动,即--privilegedprivileged:true#构建build:#构建上下文为:dockerbuild./docker-learncontext:./docker-learn#端口映射,即-p80:80ports:-80:80#对外暴露的端口,相当于Dockerfile的EXPOSE指令#EXPOSE指令只是声明了容器应该开放的端口,实际上并没有打开它!#这个选项在dockerrun-it-P(大写)中会真正起作用expose:-80#目录映射,等同于dockerrun-v#volumes:#-./logs/php-fpm:/var/log/php-fpm#-./logs/nginx:/var/log/nginx使用docker-compose启动镜像并关闭其他正在运行的容器,以免干扰我们即将运行的容器冲突dockerps|awk'{print$1}'|grep-vCON|xargsdockerkill在不使用服务名称的情况下单独启动图像将运行服务中定义的所有容器。如果services中有多个服务,可以使用up服务名单独up一个服务容器up。默认情况下,将使用build:context中的Dockerfile文件编译的镜像来启动容器。--build是强制重新编译Dockerfile重新启动镜像。但是--build仍然会使用已有镜像层的缓存--force-recreate重新编译时不使用镜像层的缓存,完全重新编译。如果有类似bind:addressalreadyinuse的提示,更改一下重试ports中的绑定端口docker-composeup[docker-learn][--build][--force-recreate]发现现在访问127.0.0.10.1:8080还是可以看到phpinfo连接jenkins进行持续集成更新连接kubernetes更新就大功告成了
