2020年了,相信大部分技术同学的开发环境都是基于docker搭建了。如果是,希望我的文章能给你带来新的收获;如果不是,那你更应该看看,了解一下为什么用docker可以让环境优雅的跳起舞来。
一般来说,我们使用docker容器技术搭建环境,有3种做法。
1. 基础做法
先从docker hub上面,下载一个centos7.x镜像。然后再依次在上面安装各种服务,如nginx, MySQL, PHP或Python等,这种做法就跟你拿到一个新的vagrant或virtualbox实例时是一样的。这几乎没有什么额外的学习成本。
1000年过去了,终于所有的服务都安装好了,配置完了,通过了环境测试,我们才能开始编码。在使用docker之前,我身边的开发同学折腾环境经常会花费整整一天的时间,非常耽误事。而当某些原因的出现,导致你需要再次折腾环境时,就得再来一次刚才的操作。对此运维同学一定感同深受,那种做着重复机械但别人又做不来的工作时的内心,一定是崩溃的。
docker hub的存在,让服务器环境也有了托管平台。为了以后安装环境方便,我们可以把自己折腾过的自己的定制环境,提交发布到hub.docker.com。(做法可以见我之前的文章: 如何将自己的容器提交到docker.com?)
然而......有时候我们会发现,用基础做法“魔改”出来的这种镜像,未必适合我们下一个项目的需求。难道我们还要再折腾一天吗?如果每个项目的环境都有差异,那么我们都得永无止境的折腾吗?
2.使用Dockerfile,定制自己的基础镜像
答案当然是“No”,因为我们可以使用Dockerfile,像开发同学编码一样来定制我们的服务器环境。而Dockerfile的语法也很简单,本文也提供了一个简单的讲解和例子供你参考。
需要说明的是,这种做法并不能完全将我们从服务环境搭建中解放出来。因为Dockerfile在设计初衷,就是为了在社区分享用的。所以类似端口映射,本地目录加载等个性化配置,是没办法写在Dockerfile里的。这就意味着,你虽然写好了一个镜像,但仍然需要很长一串加载命令。比如下面这行代码,基于某镜像的某个版本,映射常用的80,443和3306端口,加载本地的代码目录。这是非常普通的写法,实际情况可能会比这个更恶劣。
docker run -it -p 80:80/tcp,443:443/tcp,3306:3306/tcp -v /path/to/code:/var/www --names my_docker_env docker_image:version
总之,使用Dockerfile比自己运行大量的yum install(或apt-get install)命令要优雅的多。学会了Dockerfile,你可以很优雅的,像写代码一样,几分钟就把自己想要的镜像脚本写好了。剩下的事情就是让电脑代替自己去工作了,你可以悠闲的喝杯咖啡,翘起二郎腿,和自己心仪的妹子打情骂俏了。(如果有的话...... doge狗头保命)
咖啡和远方.jpg
3. 使用docker-compose让环境自己跳起舞来。
开发同学经常挂在嘴边的话就是要高内聚,低耦合。我们的开发环境也是能做到低耦合的。不同于以上两种将所有服务都塞进一个镜像容器的做法,这种做法使用了N个独立的镜像,比如MySQL镜像、Laravel镜像、nginx镜像等等,然后通过docker-compose的配置,让他们协作起来。
因为docker本身不是虚拟机,而是容器服务。就跟LOGO一样,是驮着集装箱的鲸鱼。集装箱有多少,箱里有多少货物,都是与鲸鱼无关的。每次遇到不同的项目需求,我们都可以随意增减集装箱,让这些容器就想插销一样,拔掉2个,插上1个,就能满足需要了。可以说,学会方法3才是真正发挥了docker最大优势,才是你可以拍胸膛说,“我会docker”。
docker.jpg怎么才能做到呢?
下面我会以自己的情况进行举例。我有2个自己魔改的镜像,一个是运行了nginx+php7+laravel的php开发环境,另一个则是运行了nginx+python+django的python开发环境。由于他们会用到相同的数据库,所以还有一个独立于他们的mysql数据库镜像(其实也是最简单的服务器结构,即数据与业务分离)。每次启动时,必须先启动mysql,再启动其他环境。我们的目标是:每次电脑(宿主机)重启之后,只需要让那只鲸鱼游起来,环境就直接可以使用。
我们的目标是...我们需要学习两个方面的技能,即方法2提到的Dockerfile和方法3提到的docker-compose。
什么是dockerfile?为什么要学习dockerfile?
dockerfile是docker容器技术的核心,几乎每一个docker镜像都是由dockerfile构建而成的。举个栗子:
FROM shingler/php7_laravel_nginx:v2
MAINTAINER singlerwong@qq.com
RUN apt-get install -y vim \
&& ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo 'Asia/Shanghai' > /etc/timezone
VOLUME /var/www
WORKDIR /var/www
COPY gfapi.conf /etc/nginx/conf.d
EXPOSE 8100
CMD /etc/init.d/nginx start & /etc/init.d/php7.0-fpm start & /bin/bash
上面的例子做了以下事情:基于我的魔改镜像,在启动时先安装一个vim。然后将/var/www作为目录挂载点(为了挂载本地代码目录),将当前工作目录设定为/var/www,将宿主机的现成的nginx配置拷贝到docker镜像的nginx配置目录里,同时暴露8100端口,供开发测试使用。
这里面包含了几个非常重要的命令,简述如下:
- FROM
- 你的镜像是基于哪个镜像构建的,有点像我们开发编程中的继承的概念;
- RUN
- 镜像构建时运行什么命令,一般都用来安装工具或依赖服务。比如我这里安装了vim;
- VOLUME
- 设定目录挂载点。让用于将宿主机的代码目录挂载在服务器上的nginx识别的web目录。格式是宿主机代码目录 + “:” + 服务器目录;
- WORKDIR
- 切换工作目录。如果你也想我一起要运行COPY命令,切换了WORKDIR你就可以少写前面的绝对路径了;
- COPY
- 你可以让镜像在构建时,就将提前准备好的php-fpm,hosts等配置覆盖进去了;
- EXPOSE
- 对外暴露什么端口。只有你暴露什么端口,才能映射什么端口;
- CMD
- 镜像启动时运行的命令。不同于RUN,RUN是构建时,CMD是启动时。比如我的例子里就启动了nginx和php-fpm命令。运行一个/bin/bash能够让你的容器一直处于运行状态,否则运行完,容器就退出了;
- ENTRYPOINT
- 和CMD相似,不同的是,如果你运行docker run后制定了cmd参数,dockerfile里的cmd会被覆盖(主要是挂起的那步)。entrypoint则不会,你可以继续在后面跟参数,比如
ENTRYPOINT ps -aux
这样你就可以在后面跟上grep管道过滤某些字符了。
这样的dockerfile,可以让我每次电脑重启时,不用手动修改配置了。但是运行docker run的时候,那长长的参数(目录挂载,端口映射)依然无法省略。独立的mysql容器启动之后,我还必须使用docker inspect查看mysql容器的ip地址,再去代码里修改mysql的配置项。
Dockerfile里的run命令我增加了对宿主机时间的软链接。可以有效解决docker环境与宿主机时间不一致的问题。
写好了之后,别忘记构建哦(注意运行在Dockerfile存在的目录。最后的.很重要)
docker build -t 镜像名:版本号 .
什么是docker-compose?为什么要学习docker-compose?
composer.jpg在音乐界,compose是编曲的意思。曾经有人说,会作词的没有会作曲的厉害,会作曲的没有会编曲的厉害。docker-compose就是这么一个能够编排docker镜像的工具。
通过docker compose,我们不但可以告别长长的启动参数,还可以让他们按照制定的顺序(比如先启动mysql容器再启动php容器)启动,并且固定他们的虚拟IP地址。
看下面的例子:
version: "2"
services:
laravel:
image: laravel_dev:1.7 # 加载镜像名及指定版本。
restart: always # 容器退出后自动重启。
depends_on: # 该容器依赖于哪个容器(指定启动顺序的关键)
- mysql
volumes: # 挂载代码目录
- /Users/shingler/project:/var/www
container_name: my_laravel_dev # 给容器起个中二的名字
tty: true # 进入容器时能够用linux命令操作
ports: # 端口映射
- 8100:8100
expose: # 端口暴露
- 8100
links: # 服务名,并写入hosts里。配置了这个,基本上我们就不再需要修改代码里mysql的ip地址了。
- "mysql:gf-mysql"
networks: # 使用的网络配置,可以用于固定ip地址
my_dev_workspace:
ipv4_address: 172.18.0.2
# 省略django配置,和laravel大同小异
mysql:
image: mysql:5.6
restart: always
volumes:
- /Users/shingler/database:/var/lib/mysql
container_name: mysql56
ports:
- 3306:3306
expose:
- 3306
environment: # 设置环境变量,对于mysql可以用来设置root的密码
MYSQL_ROOT_PASSWORD: 123456
networks:
my_dev_workspace:
ipv4_address: 172.18.0.3
networks: # 配置网络项,要顶格写
my_dev_workspace: # 网络配置名
driver: bridge # 网络连接方式
ipam:
driver: default
config:
- subnet: 172.18.0.0/16 # 网段
gateway: 172.18.0.1 # 网关ip
做好之后,可以运行以下命令,完成构建。
docker-compose up -d
从此之后,宿主机重启后,启动小鲸鱼,开发环境自己就跳起舞啦。如果需要增加服务,在docker-compose里,仿照上面的laravel的配置,写写就可以了。
芭蕾舞.jpg写在最后
虽说懒惰使人进步,但我们节约下来的时间和精力,绝不是要用来懒着,不能为了偷懒而偷懒。合理利用自己的时间精力,专注于更能创造价值的活动,才能做到我们的进步,是源于我们的懒惰。
希望我的文章,对你有所帮助。喜欢的话,不妨点个关注,点个赞吧!
网友评论