搭建之前,需要了解一下docker常用命令
目标
我们的目标是利用docker构建一个lnmp环境
目录结构
搭建一个lnmp环境,需要涉及到两个目录结构。一个是Dockerfile配置的目录结构,另一个是最终lnmp运行的目录结构。Dockerfile配置目录主要存放Dockerfile构建脚本和一些配置文件,lnmp运行目录主要存放程序运行产生的一些数据,比如mysql数据等。
以下是此次Dockerfile配置的目录结构,包括了nginx、php、mysql的配置文件。
lnmp
- nginx
- Dockerfile
- nginx.conf
- sites-enabled
- default.conf
...
- php
- Dockerfile
- php.ini
- php-fpm.conf
- www.conf
- mysql
- Dockerfile
- mysqld.cnf
以下是lnmp运行时的目录结构,主要是做容器内数据的持久化和共享。
/home/website
- html
- index.html
- index.php
...
- mysql
- data
...
- nginx
- logs
- access.log
- error.log
- php
- logs
- www.access.log
这里说明一下,html目录存放web网站内容,mysql目录存放的是数据库持久化的数据,nginx目录和php目录下主要存放相关运行日志。
在构建lnmp环境之前,需要先创建好这几个目录,并更改其拥有者为www-data。
另外,在部署配置lnmp之前,我们需要知道,容器内部的运行的服务,如nginx、mysql等,是会随着容器的销毁而消失的。所以
- 启动容器时,我们需要将相关的配置文件写入到容器应用程序中
- 容器运行时产生的数据,如数据库信息,我们要持久化到主机中
配置nginx
以下是nginx Dockerfile的配置
FROM nginx:1.14.2
ADD ./nginx.conf /etc/nginx/nginx.conf
ADD ./sites-enabled /etc/nginx/conf.d/
RUN mkdir -p /home/website/nginx/logs && mkdir -p /home/website/html
RUN chown -R www-data:www-data /home/website/nginx && chown -R www-data:www-data /home/website/html
该脚本主要是拉取nginx1.14.2版本的包,然后将配置文件写入到容器内部,最后创建好容器内nginx的运行目录、添加相关权限。
这里共享一下我的nginx.conf配置
user www-data;
worker_processes auto;
error_log /home/website/nginx/logs/error.log;
events {
worker_connections 1024;
}
http {
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 /home/website/nginx/logs/access.log main;
include mime.types;
default_type application/octet-stream;
sendfile on;
client_max_body_size 20m;
keepalive_timeout 65;
include /etc/nginx/conf.d/*;
}
在nginx.conf中,我将nginx的日志写入到了/home/website/nginx/logs目录下,方便持久化时目录的映射。
以下是default.conf文件内容
server {
listen 80;
root /home/website/html;
index index.php index.html index.htm;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /home/website/html;
}
location ~ \.php($|/) {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ .*\.(css|js|gif|jpg|jpeg|png|bmp|swf)$ {
expires 30d;
}
}
在default.conf中,我定义了一个简单的server,nginx的网站目录放在/home/website/html下
以上内容配置好了之后,就可以构建我们的镜像了。使用命令
docker build -t somehow/nginx ./nginx
创建好镜像somehow/nginx后,可以直接使用以下命令启动
docker run -itd -p 80:80 -v /home/website/html:/home/website/html -v /home/website/nginx/logs:/home/website/nginx/logs somehow/nginx
在启动时,我指定了相关的端口映射、目录映射以及生成的镜像名称。
接下来就可以在浏览器中访问了。当然,请确保你的工作目录,也就是主机上的/home/website/html下有你要访问的文件
配置php
以下是php Dockerfile的配置
FROM php:7.2-fpm
ADD ./php.ini /usr/local/etc/php/php.ini
ADD ./php-fpm.conf /usr/local/etc/php-fpm.conf
ADD ./www.conf /usr/local/etc/php-fpm.d/www.conf
RUN apt-get update && apt-get install -y \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install -j$(nproc) gd \
&& docker-php-ext-install pdo_mysql \
&& docker-php-ext-install opcache \
&& apt-get install -y libxml2-dev \
&& docker-php-ext-install xml \
&& docker-php-ext-install bcmath \
&& docker-php-ext-install soap \
&& docker-php-ext-install zip
RUN pecl install redis-4.0.1 \
&& pecl install xdebug-2.6.0 \
&& docker-php-ext-enable redis xdebug
RUN mkdir -p /home/website/html && mkdir -p /home/website/php/logs
RUN chown -R www-data:www-data /home/website/html && chown -R www-data:www-data /home/website/php/logs
WORKDIR /home/website/html
php的构建文件内容比较多,但是基本都是Docker hub中说明过的一些操作,包括:
- 确定基础镜像为7.2版本的php-fpm
- 添加配置文件到容器中
- 安装容器扩展
- 创建工作目录,修改相应权限
关于其中的一些配置文件,其实可以从原始的php-fpm镜像中拷贝出来,然后再进行个性化的修改,添加进入容器中。我自己个人修改了www.conf这个文件,修改了其中两点:
- listen = 127.0.0.1:9000
- access.log = /home/website/php/logs/$pool.access.log
即设置了php-fpm的端口,并指定了访问日志文件的存放路径
接下来就可以创建镜像,使用命令
docker build -t somehow/php ./php
启动该镜像,使用命令
docker run -itd -p 9000:9000 -v /home/website/html:/home/website/html -v /home/website/php/logs:/home/website/php/logs somehow/php
同样,这里进行了端口映射和目录映射。
部署好php还不够,我们还要将php和nginx连接起来,从而将php请求发送php-fpm进行处理。
将上述nginx配置文件中的default.conf中,php连接的地址改为主机的ip地址+端口号9000,修改部分如下
location ~ \.php($|/) {
fastcgi_pass **主机的ip**:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
这里注意要使用主机的ip而不是127.0.0.1。因为127.0.0.1配置的是容器内部的地址,放在外部是无法访问的,但是启动容器的时候进行了端口映射,所以可以通过主机端口来进行一次中转,从而将请求发送给正确的服务来处理。
配置好之后,重新build,run。nginx已经可以处理php请求了。
配置mysql
以下是mysql Dockerfile的配置
FROM mysql:5.7
Add ./mysqld.cnf /etc/mysql/mysql.conf.d/mysqld.cnf
MySQL的配置非常简单,直接拉取mysql5.7的官方镜像,然后添加配置文件到容器即可。
然后创建镜像,使用命令
docker build -t somehow/mysql ./mysql
启动该镜像,使用命令
docker run -itd -p 3306:3306 -v /home/website/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 somehow/mysql
mysql镜像的启动方式与上述两者略有不同,除了端口映射以及目录映射外,还新增了一个环境变量MYSQL_ROOT_PASSWORD,这个变量是官方景象中启动容器所必须指定的,代表着root用户的初始密码。
启动完成之后,现在使用数据库远程连接工具连接mysql,应当是可以连接成功的。
接下来是php与mysql的整合。
和nginx整合php的方式类似,php代码中若要调用mysql,需要在代码中指定主机的IP,而不能简单的使用127.0.0.1。
这里提供一个验证脚本,可以用来进行连接的验证
<?php
$dbms='mysql'; //数据库类型
$host=''; //数据库主机IP(使用真实主机IP)
$dbName='mysql'; //使用的数据库
$user='root'; //数据库连接用户名
$pass='123456'; //对应的密码
$dsn="$dbms:host=$host;dbname=$dbName";
try {
$dbh = new PDO($dsn, $user, $pass); //初始化一个PDO对象
echo "连接成功<br/>";
} catch (PDOException $e) {
die ("Error!: " . $e->getMessage() . "<br/>");
}
//默认这个不是长连接,如果需要数据库长连接,需要最后加一个参数:array(PDO::ATTR_PERSISTENT => true) 变成这样:
$db = new PDO($dsn, $user, $pass, array(PDO::ATTR_PERSISTENT => true));
将该脚本部署到相应目录下,通过网页打开,会得到连接mysql成功的提示。你会注意到这里我们直接就能连接mysql,这是因为在php的构建过程中,我们已经在脚本中加入了pdo_mysql的扩展。
总结
以上就是使用docker构建lnmp运行环境的步骤。
以上的步骤看起来很复杂,但是当我们拿到一个新系统、需要搭建环境的时候,使用预先制作好的Dockerfile脚本无疑比手工重复快捷多了。
这其中当然有可以优化的部分,但是使用docker-compose无疑是更优的选择。关于docker-compose以及关于lnmp使用过程中的一些问题和坑,我会在接下来的几篇博文中记录下来,希望能对大家有所帮助。
另:构建lnmp环境的Dockerfile的配置文件已经上传,可以点击此处进行下载。
以上内容如有错误,或在使用过程中有问题,欢迎指正。