Docker LNMP 开发环境搭建

准确的说,使用 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
# Dockerfile必有的语句 FROM php:7-fpm-alpine3.7 表示 library/php 官方仓库,基于3.7 alpine linux构建的php7的php-fpm镜像
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
# pecl install 安装比较慢,所以事先把源码下载下来安装
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
# 安装zip扩展
RUN apk add --no-cache zlib-dev \
&& docker-php-ext-install zip\
&& apk del zlib-dev
# 安装gd扩展
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
# 安装imagick扩展
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
# 安装mcrypt扩展
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
# 安装redis,mongodb扩展
RUN pecl install /tmp/php-exts/redis*.tgz /tmp/php-exts/mongodb*.tgz \
&& docker-php-ext-enable redis mongodb
# 安装composer
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
# 安装xdebug扩展,并修改配置
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
# 添加非root用户
RUN adduser -D -u 1000 alitain
# 切换到非root用户
USER alitain
# 设置工作目录
WORKDIR /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 # nginx 配置文件和本地映射
depends_on: # nginx 容器依赖启动依赖 php5 和 php7
- php5
- php7
volumes_from: # 卷继承自 app
- 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 查看是否可以从镜像服务器上拉取镜像并成功运行。

显示 Gitment 评论