使用Docker 一键部署 LNMP+Redis 环境

32次阅读

共计 8755 个字符,预计需要花费 22 分钟才能阅读完成。

使用 Docker 部署 LNMP+Redis 环境
Docker 简介
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。推荐内核版本 3.8 及以上
为什么使用 Docker

加速本地的开发和构建流程,容器可以在开发环境构建,然后轻松地提交到测试环境,并最终进入生产环境
能够在让独立的服务或应用程序在不同的环境中得到相同的运行结果
创建隔离的环境来进行测试
高性能、超大规划的宿主机部署
从头编译或者扩展现有的 OpenShift 或 Cloud Foundry 平台来搭建自己的 PaaS 环境

目录

安装 Docker
目录结构
快速使用
进入容器内部
PHP 扩展安装
Composer 安装
常见问题处理
常用命令
Dockerfile 语法
docker-compose 语法说明

项目源码地址:GitHub

安装 Docker
windows 安装
参考
mac
docker toolbox 参考
linux
# 下载安装
curl -sSL https://get.docker.com/ | sh

# 设置开机自启
sudo systemctl enable docker.service

sudo service docker start|restart|stop

# 安装 docker-compose
curl -L https://github.com/docker/compose/releases/download/1.23.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
目录结构
docker_lnmp
├── v2
├── mysql
│ └── Dockerfile
│ └── my.cnf
├── nginx
│ ├── Dockerfile
│ ├── nginx.conf
│ ├── log
│ │ └── error.log
│ └── www
│ ├── index.html
│ ├── index.php
│ ├── db.php
│ └── redis.php
├── php
│ ├── Dockerfile
│ ├── www.conf
│ ├── php-fpm.conf
│ ├── php.ini
│ └── log
│ └── php-fpm.log
└── redis
└── Dockerfile
└── redis.conf
创建镜像与安装
直接使用 docker-compose 一键制作镜像并启动容器
版本一
该版本是通过拉取纯净的 CentOS 镜像,通过 Dockerfile 相关命令进行源码编译安装各个服务。所以该方式很方便定制自己需要的镜像,但是占用空间大且构建慢。
git clone https://github.com/voocel/docker-lnmp.git
cd docker-lnmp
docker-compose up -d
版本二(推荐)
git clone https://github.com/voocel/docker-lnmp.git
cd docker-lnmp/v2
chmod 777 ./redis/redis.log
chmod -R 777 ./redis/data
docker-compose up -d
该版本是通过拉取官方已经制作好的各个服务的镜像,再通过 Dockerfile 相关命令根据自身需求做相应的调整。所以该方式构建迅速使用方便,因为是基于 Alpine Linux 所以占用空间很小。
测试
使用 docker ps 查看容器启动状态, 若全部正常启动了则通过访问 127.0.0.1、127.0.0.1/index.php、127.0.0.1/db.php、127.0.0.1/redis.php 即可完成测试(若想使用 https 则请修改 nginx 下的 dockerfile,和 nginx.conf 按提示去掉注释即可,灵需要在 ssl 文件夹中加入自己的证书文件,本项目自带的是空的,需要自己替换,保持文件名一致)
进入容器内部
使用 docker exec
docker exec -it ngixn /bin/sh
使用 nsenter 命令
# cd /tmp; curl https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz | tar -zxf-; cd util-linux-2.24;
# ./configure –without-ncurses
# make nsenter && sudo cp nsenter /usr/local/bin
为了连接到容器,你还需要找到容器的第一个进程的 PID,可以通过下面的命令获取再执行。
PID=$(docker inspect –format “{{ .State.Pid}}” container_id)
# nsenter –target $PID –mount –uts –ipc –net –pid
PHP 扩展安装
安装 PHP 官方源码包里的扩展(如:同时安装 pdo_mysql mysqli pcntl gd 四个个扩展)
在 php 的 Dockerfile 中加入以下命令
RUN apk add libpng-dev \
&& docker-php-ext-install pdo_mysql mysqli pcntl gd \
注: 因为该镜像缺少 gd 库所需的 libpng-dev 包,所以需要先下载这个包
PECL 扩展安装
# 安装扩展
RUN pecl install memcached-2.2.0 \
# 启用扩展
&& docker-php-ext-enable memcached \
通过下载扩展源码,编译安装的方式安装
# 安装 Redis 和 swoole 扩展
RUN cd ~ \
&& wget https://github.com/phpredis/phpredis/archive/4.2.0.tar.gz \
&& tar -zxvf 4.2.0.tar.gz \
&& mkdir -p /usr/src/php/ext \
&& mv phpredis-4.2.0 /usr/src/php/ext/redis \
&& docker-php-ext-install redis \

&& apk add libstdc++\
&& cd ~ \
&& wget https://github.com/swoole/swoole-src/archive/v4.2.12.tar.gz \
&& tar -zxvf v4.2.12.tar.gz \
&& mkdir -p /usr/src/php/ext \
&& mv swoole-src-4.2.12 /usr/src/php/ext/swoole \
&& docker-php-ext-install swoole \
注: 因为该镜像需要先安装 swoole 依赖的 libstdc++,否则安装成功后无法正常加载 swoole 扩展
Composer 安装
在 Dockerfile 中加入
RUN curl -sS https://getcomposer.org/installer | php — –install-dir=/usr/bin/ –filename=composer \
常见问题处理
redis 启动失败问题
在 v2 版本中 redis 的启动用户为 redis 不是 root, 所以在宿主机中挂载的./redis/redis.log 和./redis/data 需要有写入权限。
chmod 777 ./redis/redis.log
chmod 777 ./redis/data
MYSQL 连接失败问题
在 v2 版本中是最新的 MySQL8, 而该版本的密码认证方式为 Caching_sha2_password, 而低版本的 php 和 mysql 可视化工具可能不支持, 可通过 phpinfo 里的 mysqlnd 的 Loaded plugins 查看是否支持该认证方式, 否则需要修改为原来的认证方式 mysql_native_password:
select user,host,plugin,authentication_string from mysql.user;
ALTER USER ‘root’@’%’ IDENTIFIED WITH mysql_native_password BY ‘123456’;
FLUSH PRIVILEGES;

注意挂载目录的权限问题,不然容器成功启动几秒后立刻关闭,例:以下 /data/run/mysql 目录没权限的情况下就会出现刚才那种情况
docker run –name mysql57 -d -p 3306:3306 -v /data/mysql:/var/lib/mysql -v /data/logs/mysql:/var/log/mysql -v /data/run/mysql:/var/run/mysqld -e MYSQL_ROOT_PASSWORD=123456 -it centos/mysql:v5.7

需要注意 php.ini 中的目录对应 mysql 的配置的目录需要挂载才能获取文件内容,不然 php 连接 mysql 失败
# php.ini
mysql.default_socket = /data/run/mysql/mysqld.sock
mysqli.default_socket = /data/run/mysql/mysqld.sock
pdo_mysql.default_socket = /data/run/mysql/mysqld.sock

# mysqld.cnf
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock

使用 php 连接不上 redis
# 错误的
$redis = new Redis;
$rs = $redis->connect(‘127.0.0.1’, 6379);

php 连接不上,查看错误日志
PHP Fatal error: Uncaught RedisException: Redis server went away in /www/index.php:7
考虑到 docker 之间的通信应该不可以用 127.0.0.1 应该使用容器里面的 ip,所以查看 redis 容器的 ip
[root@localhost docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b5f7dcecff4c docker_nginx “/usr/sbin/nginx -…” 4 seconds ago Up 3 seconds 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp nginx
60fd2df36d0e docker_php “/usr/local/php/sb…” 7 seconds ago Up 5 seconds 9000/tcp php
7c7df6f8eb91 hub.c.163.com/library/mysql:latest “docker-entrypoint…” 12 seconds ago Up 11 seconds 3306/tcp mysql
a0ebd39f0f64 docker_redis “usr/local/redis/s…” 13 seconds ago Up 12 seconds 6379/tcp redis
注意测试的时候连接地址需要容器的 ip 或者容器名 names,比如 redis、mysql. 例如 nginx 配置 php 文件解析 fastcgi_pass php:9000; 例如 php 连接 redis $redis = new Redis;$res = $redis->connect(‘redis’, 6379);
因为容器 ip 是动态的,重启之后就会变化,所以可以创建静态 ip
第一步:创建自定义网络
#备注:这里选取了 172.172.0.0 网段,也可以指定其他任意空闲的网段
docker network create –subnet=172.171.0.0/16 docker-at
docker run –name redis326 –net docker-at –ip 172.171.0.20 -d -p 6379:6379 -v /data:/data -it centos/redis:v3.2.6
连接 redis 就可以配置对应的 ip 地址了,连接成功
$redis = new Redis;
$rs = $redis->connect(‘172.171.0.20’, 6379);
另外还有种可能 phpredis 连接不上 redis,需要把 redis.conf 配置略作修改。
bind 127.0.0.1
改为:
bind 0.0.0.0

启动 docker web 服务时 虚拟机端口转发 外部无法访问 一般出现在 yum update 的时候(WARNING: IPv4 forwarding is disabled. Networking will not work.)或者宿主机可以访问,但外部无法访问

vi /etc/sysctl.conf
或者
vi /usr/lib/sysctl.d/00-system.conf
添加如下代码:
net.ipv4.ip_forward=1

重启 network 服务
systemctl restart network

查看是否修改成功
sysctl net.ipv4.ip_forward

如果返回为 ”net.ipv4.ip_forward = 1″ 则表示成功了
如果使用最新的 MySQL8 无法正常连接,由于最新版本的密码加密方式改变,导致无法远程连接。
# 修改密码加密方式
ALTER USER ‘root’@’%’ IDENTIFIED WITH mysql_native_password BY ‘123456’;
常用命令

docker start 容器名(容器 ID 也可以)

docker stop 容器名(容器 ID 也可以)

docker run 命令加 -d 参数,docker 会将容器放到后台运行

docker ps 正在运行的容器

docker logs –tail 10 -tf 容器名 查看容器的日志文件, 加 - t 是加上时间戳,f 是跟踪某个容器的最新日志而不必读整个日志文件

docker top 容器名 查看容器内部运行的进程

docker exec -d 容器名 touch /etc/new_config_file 通过后台命令创建一个空文件

docker run –restart=always –name 容器名 -d ubuntu /bin/sh -c “while true;do echo hello world; sleep 1; done” 无论退出代码是什么,docker 都会自动重启容器,可以设置 –restart=on-failure:5 自动重启的次数

docker inspect 容器名 对容器进行详细的检查,可以加 –format='{(.State.Running)}’ 来获取指定的信息

docker rm 容器 ID 删除容器,注,运行中的容器无法删除

docker rm $(docker ps -aq) 删除所有容器

docker rmi $(docker images -aq) 删除所有镜像

docker images 列出镜像

docker pull 镜像名: 标签 拉镜像

docker search 查找 docker Hub 上公共的可用镜像

docker build -t=’AT/web_server:v1′ 命令后面可以直接加上 github 仓库的要目录下存在的 Dockerfile 文件。命令是编写 Dockerfile 之后使用的。- t 选项为新镜像设置了仓库和名称: 标签

docker login 登陆到 Docker Hub,个人认证信息将会保存到 $HOME/.dockercfg,

docker commit -m=”comment ” –author=”AT” 容器 ID 镜像的用户名 / 仓库名: 标签 不推荐这种方法,推荐 dockerfile

docker history 镜像 ID 深入探求镜像是如何构建出来的

docker port 镜像 ID 端口 查看映射情况的容器的 ID 和容器的端口号,假设查询 80 端口对应的映射的端口

run 运行一个容器,-p 8080:80 将容器内的 80 端口映射到 docker 宿主机的某一特定端口,将容器的 80 端口绑定到宿主机的 8080 端口,另 127.0.0.1:80:80 是将容器的 80 端口绑定到宿主机这个 IP 的 80 端口上,-P 是将容器内的 80 端口对本地的宿主机公开

http://docs.docker.com/refere… 查看更多的命令

docker push 镜像名 将镜像推送到 Docker Hub

docker rmi 镜像名 删除镜像

docker attach 容器 ID 进入容器

docker network create –subnet=172.171.0.0/16 docker-at 选取 172.172.0.0 网段

docker build 就可以加 -ip 指定容器 ip 172.171.0.10 了

删除所有容器和镜像的命令
docker rm `docker ps -a |awk ‘{print $1}’ | grep [0-9a-z]` 删除停止的容器
docker rmi $(docker images | awk ‘/^<none>/ { print $3}’)
Dockerfile 语法

MAINTAINER 标识镜像的作者和联系方式

EXPOSE 可以指定多个 EXPOSE 向外部公开多个端口,可以帮助多个容器链接

FROM 指令指定一个已经存在的镜像

\# 号代表注释

RUN 运行命令, 会在 shell 里使用命令包装器 /bin/sh -c 来执行。如果是在一个不支持 shell 的平台上运行或者不希望在 shell 中运行,也可以 使用 exec 格式 的 RUN 指令

ENV REFRESHED_AT 环境变量 这个环境亦是用来表明镜像模板最后的更新时间

VOLUME 容器添加卷。一个卷是可以 存在于一个或多个容器内的特定的目录,对卷的修改是立刻生效的,对卷的修改不会对更新镜像产品影响,例:VOLUME[“/opt/project”,”/data”]

ADD 将构建环境 下的文件 和目录复制到镜像 中。例 ADD nginx.conf /conf/nginx.conf 也可以是取 url 的地址文件,如果是压缩包,ADD 命令会自动解压、

USER 指定镜像用那个 USER 去运行

COPY 是复制本地文件,而不会去做文件提取(解压包不会自动解压)例:COPY conf.d/ /etc/apache2/ 将本地 conf.d 目录中的文件复制到 /etc/apache2/ 目录中

docker-compose.yml 语法说明

image 指定为镜像名称或镜像 ID。如果镜像不存在,Compose 将尝试从互联网拉取这个镜像

build 指定 Dockerfile 所在文件夹的路径。Compose 将会利用他自动构建这个镜像,然后使用这个镜像

command 覆盖容器启动后默认执行的命令

links 链接到其他服务容器,使用服务名称 (同时作为别名) 或服务别名(SERVICE:ALIAS)都可以

external_links 链接到 docker-compose.yml 外部的容器,甚至并非是 Compose 管理的容器。参数格式和 links 类似

ports 暴露端口信息。宿主机器端口:容器端口(HOST:CONTAINER)格式或者仅仅指定容器的端口(宿主机器将会随机分配端口)都可以(注意:当使用 HOST:CONTAINER 格式来映射端口时,如果你使用的容器端口小于 60 你可能会得到错误得结果,因为 YAML 将会解析 xx:yy 这种数字格式为 60 进制。所以建议采用字符串格式。)

expose 暴露端口,与 posts 不同的是 expose 只可以暴露端口而不能映射到主机,只供外部服务连接使用;仅可以指定内部端口为参数

volumes 设置卷挂载的路径。可以设置宿主机路径: 容器路径(host:container)或加上访问模式(host:container:ro)ro 就是 readonly 的意思,只读模式

volunes_from 挂载另一个服务或容器的所有数据卷

environment 设置环境变量。可以属于数组或字典两种格式。如果只给定变量的名称则会自动加载它在 Compose 主机上的值,可以用来防止泄露不必要的数据

env_file 从文件中获取环境变量,可以为单独的文件路径或列表。如果通过 docker-compose -f FILE 指定了模板文件,则 env_file 中路径会基于模板文件路径。如果有变量名称与 environment 指令冲突,则以后者为准(环境变量文件中每一行都必须有注释,支持 #开头的注释行)

extends 基于已有的服务进行服务扩展。例如我们已经有了一个 webapp 服务,模板文件为 common.yml。编写一个新的 development.yml 文件,使用 common.yml 中的 webapp 服务进行扩展。后者会自动继承 common.yml 中的 webapp 服务及相关的环境变量

net 设置网络模式。使用和 docker client 的 –net 参数一样的值

pid 和宿主机系统共享进程命名空间,打开该选项的容器可以相互通过进程 id 来访问和操作

dns 配置 DNS 服务器。可以是一个值,也可以是一个列表

cap_add,cap_drop 添加或放弃容器的 Linux 能力(Capability)

dns_search 配置 DNS 搜索域。可以是一个值也可以是一个列表
注意:使用 compose 对 Docker 容器进行编排管理时,需要编写 docker-compose.yml 文件,初次编写时,容易遇到一些比较低级的问题,导致执行 docker-compose up 时先解析 yml 文件的错误。比较常见的是 yml 对缩进的严格要求。yml 文件还行后的缩进,不允许使用 tab 键字符,只能使用空格,而空格的数量也有要求,一般两个空格。

项目源码地址:GitHub

正文完
 0