准确的说,使用 docker 搭建的 LNMP 环境已经不算是 LNMP 了,因为 nginx、mysql、php 并不是运行在 linux 上,而是运行在 docker 平台上(实际上是运行在本机系统独立的进程空间里),而 docker 平台可以运行在个人笔记本、服务器、公有云等几乎所有的设备上,并且是跨操作系统的。下面一起来搭建一个 DNMP 环境,并将镜像推送到私有镜像服务器。Github代码 alitain/dnmp 。
前期准备 首先,我们要根据自己的操作系统,安装对应的 docker。下面以 Mac 为例,下载 Docker For Mac 安装,成功之后从偏好设置中修改 Deamon 的设置添加中国镜像地址。例如 docker中国,daocloud,阿里云等镜像地址,以docker中国为例,填入 https://registry.docker-cn.com后,应用重启。
我们可以在命令行执行 docker pull library/registry 查看镜像加速是否配置成功。
编写 Dockerfile 在docker 商店 中已经提供了很多官方镜像和社区镜像,但是并不一定会满足我们的需求,所以我们要基于官方镜像进行修改。考虑到 php 版本的兼容性,这里会同时部署php5,和php7两个版本。nginx 和 mysql 也会分别基于官方镜像进行修改,除此之外还会添加一个专门用于映射代码和在容器之间同步代码的一个镜像。
下面以 php7 为例,简单介绍一下镜像构建流程
首先,我们创建一个 dnmp/php7 的目录,在这个目录下新建一个 Dockerfile 文件,输入一下内容
1 2 3 4 5 6 7 8 FROM php:7 -fpm-alpine3.7 CMD ["php-fpm" ] EXPOSE 9000
然后在 php7 目录下执行 docker build . -t alitain/php7,我们基于官方的php7镜像,构建了自己的镜像,并且打了一个标签叫做 alitain/php7。执行docker image ls可以看见我们刚刚构建出来的镜像。
构建完成后,执行 docker run -it alitain/php7 /bin/bash 进入容器,执行 php -v查看 php 版本。我们只继承了官方的镜像,并没有做任何修改,下面我们加入一些扩展,使镜像可以满足我们的开发需要
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 FROM php:7 -fpm-alpine3.7 COPY exts /tmp/php-exts RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/' /etc/apk/repositories RUN apk add --no-cache autoconf gcc g++ make git RUN apk add --no-cache freetype libpng libjpeg-turbo libmcrypt libtool RUN docker-php-ext-install iconv pdo_mysql RUN apk add --no-cache zlib-dev \ && docker-php-ext-install zip\ && apk del zlib-dev RUN apk add --no-cache freetype-dev libpng-dev libjpeg-turbo-dev && \ docker-php-ext-configure gd \ --with-gd \ --with-freetype-dir=/usr/include/ \ --with-png-dir=/usr/include/ \ --with-jpeg-dir=/usr/include/ && \ docker-php-ext-install -j$(getconf _NPROCESSORS_ONLN) gd && \ apk del --no-cache freetype-dev libpng-dev libjpeg-turbo-dev RUN apk add --no-cache imagemagick-dev imagemagick\ && pecl install /tmp/php-exts/imagick*.tgz \ && docker-php-ext-enable imagick \ && apk del --no-cache imagemagick-dev RUN apk add --no-cache libmcrypt-dev \ && pecl install /tmp/php-exts/mcrypt*.tgz \ && docker-php-ext-enable mcrypt \ && apk del --no-cache libmcrypt-dev RUN pecl install /tmp/php-exts/redis*.tgz /tmp/php-exts/mongodb*.tgz \ && docker-php-ext-enable redis mongodb RUN apk add --no-cache wget \ && wget https://getcomposer.org/download/1.6.5/composer.phar \ && mv composer.phar /usr/local /bin/composer \ && chmod +x /usr/local /bin/composer \ && composer config -g repo.packagist composer https://packagist.phpcomposer.com \ && apk del wget RUN pecl install /tmp/php-exts/xdebug*.tgz \ && docker-php-ext-enable xdebug \ && echo -e 'xdebug.remote_enable=1\nxdebug.remote_host=host.docker.internal\nxdebug.remote_port=9000\nxdebug.idekey=PHPSTORM' >> /usr/local /etc/php/conf.d/docker-php-ext-xdebug.ini RUN adduser -D -u 1000 alitain USER alitainWORKDIR /var/www CMD ["php-fpm" ] EXPOSE 9000
重新执行 build 操作,新的镜像默认会把旧的镜像覆盖掉,执行 docker run 进入容器,执行 php -m 查看扩展是否安装正确。
nginx、php5、mysql、share的构建都是类似的操作,为了满足下文的需要,构建镜像的时候,标签名称统一加上 alitain/ 的前缀。
服务编排 如何让这些容器在一起工作,并指定 nginx 对外提供服务绑定本机端口,答案就是docker-compose。很简单我们只需要在 dnmp/ 目录下新建一个docker-compose.yaml的配置文件,配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 version: '2' services: app: image: alitain/share volumes: - ../../code/alitain/:/var/www nginx: image: alitain/nginx ports: - "8080:8080" volumes: - ./nginx/sites:/etc/nginx/sites-available depends_on: - php5 - php7 volumes_from: - app php7: image: alitain/php7 volumes_from: - app php5: image: alitain/php5 volumes_from: - app mysql: image: alitain/mysql ports: - "3306:3306" user: mysql volumes: - ./mysql/data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: root
配置好后,执行docker-compose up -d就可以启动我们构建的容器了。在浏览器中访问 http://localhost:8080 查看效果。
把镜像推送到私有镜像服务器上 为了方便调试,我们可以把镜像服务器搭建在本地,然后删除已构建的镜像,从本地镜像服务器上拉取镜像。Docker 的镜像服务器搭建很方便,使用官方镜像服务器镜像就能够满足需要。在上面的步骤中,我们拉取过 library/registry 镜像。所以只要启动这个镜像就可以了,当然如果启动镜像的时候,镜像不存在也会从配置中的镜像服务器上一一尝试去拉取。
在命令行执行 docker run -d -p 5000:5000 -v /path/to/store/images:/var/lib/registry library/registry启动镜像服务,-d 表示以在后台运行,-p 映射容器的 5000 端口到本地, -v 映射镜像保存目录,用户持久化保存镜像,下次启动的时候之前的镜像还在。
如何让我们的镜像服务器在 docker 中生效呢,需要像前面那样修改镜像服务器配置。添加 http://127.0.0.1:5000 到镜像服务器配置中,由于我们没有使用 https,所以还需要再不安全服务器上添加 127.0.0.1:5000。
接下来,我们推送镜像到镜像服务器上。首先给镜像打一个标签,以 php7 镜像为例 docker tag alitain/php7 127.0.0.0:5000/alitain/php7:latest,推送镜像 docker push 127.0.0.0:5000/alitain/php7:latest。
删除我们的自定义镜像,docker rmi --forece $(docker images | grep alitain | awk '{print $3}')。在 dnmp/ 目录下执行 dockr-compose up -d 查看是否可以从镜像服务器上拉取镜像并成功运行。