alpine install Nginx + PHP5 + MySQL5
Foreword
alpine version 3.6
PHP version 5.6
MySQL actually uses MariaDB in alpine, this time installed 10.1 corresponding to MySQL 5.6.
The alpine software package queries the
correspondence between MariaDB and MySQL versions.
Convention: The one-time operations in the following chapters are all written in the 配置
section.
Manual installation
Ready to work
# 启动容器,注意:全程用root 操作!
docker run -d -p 8080:80 --name mnp5 alpine:3.6 /sbin/init
# 简单解释:-d 容器后台运行,-p 映射宿主机端口,执行/sbin/init 才能使用openrc 及reboot 等命令,默认sh 不行
# 如果不想终止容器而退出来的话可以用Ctrl+p 再Ctrl+q,再想进入容器
docker exec -it mnp5 sh
# 简单解释:-it 获得输入输出
# 更新软件包索引
apk update
1 Nginx
1.1 Installation
apk add nginx
1.2 Configuration
# 创建www 组和www 用户,用于运行nginx,否则用root 权限太大太危险
adduser -D -g 'www' www
# 创建用于存放网页文件的目录,且归属于www 组及www 用户
mkdir /www
chown -R www:www /var/lib/nginx
chown -R www:www /www
# alpine 的nginx 没有默认站点目录,需在配置中用root 属性指定,后面有样例
# 备份nginx 默认配置
mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.orig
# 创建nginx 运行所需的目录
mkdir /run/nginx/
Edit Nginx
configuration filevi /etc/nginx/nginx.conf
user www;
worker_processes auto; # it will be determinate automatically by the number of core
error_log /var/log/nginx/error.log warn;
#pid /var/run/nginx/nginx.pid; # it permit you to use /etc/init.d/nginx reload|restart|stop|start
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
access_log /var/log/nginx/access.log;
keepalive_timeout 3000;
server {
listen 80;
root /www;
index index.html index.htm;
server_name localhost;
client_max_body_size 32m;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /var/lib/nginx/html;
}
}
}
Create a page filevi /www/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>HTML5</title>
</head>
<body>
Server is online
</body>
</html>
1.3 Inspection
# 启动nginx,启动之前先检查一下配置文件是否正确
nginx -t && nginx
Open the browser to access the localhost:8080
display on the host machine, Server is online
it means that the installation and configuration is successful.
Check the log if you have problems less /var/log/nginx/error.log
.
2 PHP
2.1 Installation
# 可根据需求apk update && apk search php5 来查找要安装的包
apk add php5 php5-ctype php5-curl php5-dom php5-fpm php5-iconv php5-gd \
php5-json php5-mysqli php5-openssl php5-pdo php5-pdo_sqlite \
php5-sqlite3 php5-xml php5-xmlreader php5-zlib php5-phar php5-posix
2.2 Configuration
# 创建环境变量,后面生成配置文件会用到
PHP_FPM_USER="www"
PHP_FPM_GROUP="www"
PHP_FPM_LISTEN_MODE="0660"
PHP_MEMORY_LIMIT="512M"
PHP_MAX_UPLOAD="50M"
PHP_MAX_FILE_UPLOAD="200"
PHP_MAX_POST="100M"
PHP_DISPLAY_ERRORS="On"
PHP_DISPLAY_STARTUP_ERRORS="On"
PHP_ERROR_REPORTING="E_COMPILE_ERROR\|E_RECOVERABLE_ERROR\|E_ERROR\|E_CORE_ERROR"
PHP_CGI_FIX_PATHINFO=0
# 编辑/etc/php5/php-fpm.conf
sed -i "s|;listen.owner\s*=\s*nobody|listen.owner = ${PHP_FPM_USER}|g" /etc/php5/php-fpm.conf
sed -i "s|;listen.group\s*=\s*nobody|listen.group = ${PHP_FPM_GROUP}|g" /etc/php5/php-fpm.conf
sed -i "s|;listen.mode\s*=\s*0660|listen.mode = ${PHP_FPM_LISTEN_MODE}|g" /etc/php5/php-fpm.conf
sed -i "s|user\s*=\s*nobody|user = ${PHP_FPM_USER}|g" /etc/php5/php-fpm.conf
sed -i "s|group\s*=\s*nobody|group = ${PHP_FPM_GROUP}|g" /etc/php5/php-fpm.conf
sed -i "s|;log_level\s*=\s*notice|log_level = notice|g" /etc/php5/php-fpm.conf
# 编辑/etc/php5/php.ini
sed -i "s|display_errors\s*=\s*Off|display_errors = ${PHP_DISPLAY_ERRORS}|i" /etc/php5/php.ini
sed -i "s|display_startup_errors\s*=\s*Off|display_startup_errors = ${PHP_DISPLAY_STARTUP_ERRORS}|i" /etc/php5/php.ini
sed -i "s|error_reporting\s*=\s*E_ALL & ~E_DEPRECATED & ~E_STRICT|error_reporting = ${PHP_ERROR_REPORTING}|i" /etc/php5/php.ini
sed -i "s|;*memory_limit =.*|memory_limit = ${PHP_MEMORY_LIMIT}|i" /etc/php5/php.ini
sed -i "s|;*upload_max_filesize =.*|upload_max_filesize = ${PHP_MAX_UPLOAD}|i" /etc/php5/php.ini
sed -i "s|;*max_file_uploads =.*|max_file_uploads = ${PHP_MAX_FILE_UPLOAD}|i" /etc/php5/php.ini
sed -i "s|;*post_max_size =.*|post_max_size = ${PHP_MAX_POST}|i" /etc/php5/php.ini
sed -i "s|;*cgi.fix_pathinfo=.*|cgi.fix_pathinfo= ${PHP_CGI_FIX_PATHINFO}|i" /etc/php5/php.ini
Modify the Nginx
configuration vi /etc/nginx/nginx.conf
to php-fpm5
connect with
# /etc/nginx/nginx.conf
user www;
worker_processes auto;
pcre_jit on;
error_log /var/log/nginx/error.log warn;
include /etc/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
server_tokens off;
client_max_body_size 1m;
keepalive_timeout 65;
sendfile on;
tcp_nodelay on;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:2m;
gzip_vary on;
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 /var/log/nginx/access.log main;
server {
listen 80;
root /www;
index index.html index.htm index.php;
server_name localhost;
client_max_body_size 32m;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /var/lib/nginx/html;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
}
}
Basically, /etc/nginx/nginx.conf
remove the comments and the last of the original content include /etc/nginx/conf.d/*.conf;
, server
write the configuration directly here, and set the running user to www
; there is also the fastcgi_pass 127.0.0.1:9000
corresponding /etc/php5/php-fpm.conf
, in listen = 127.0.0.1:9000
order php
to transfer the page to php-fpm
processing.
Create php
test pagevi /www/info.php
<?php phpinfo(); ?>
Set time zone (optional)
# 加载时区数据
apk add tzdata
# 设置时区
TIMEZONE="Asia/Shanghai"
cp /usr/share/zoneinfo/${TIMEZONE} /etc/localtime
echo "${TIMEZONE}" > /etc/timezone
sed -i "s|;*date.timezone =.*|date.timezone = ${TIMEZONE}|i" /etc/php5/php.ini
2.3 Inspection
# 杀掉后台nginx 和php-fpm5 进程
killall nginx php-fpm5
# 先启动php-fpm5 感觉好一点
php-fpm5
# 启动nginx,启动之前先检查一下配置文件是否正确
nginx -t && nginx
# 如果之前没有杀死nginx 进程也可以让其重新读取配置
nginx -s reload
Open the browser in the host machine to access localhost:8080/info.php
and see the current php
relevant information (version number, module, etc.).
3 MySQL
3.1 Installation
# alpine 中MySQL 用的就是MariaDB
apk add mysql mysql-client
# 或
apk add mariadb mariadb-client
3.2 Configuration
# 创建运行mysqld 后台进程必须的目录并赋给mysql 组和mysql 用户
mkdir -p /run/mysqld
chown -R mysql:mysql /run/mysqld
# 加载数据库文件
chown -R mysql:mysql /var/lib/mysql
mysql_install_db --user=mysql --ldata=/var/lib/mysql
3.3 Inspection
# 启动mysqld,注意加个& 后台运行,否则只能Ctrl+p,Ctrl+q 退出再docker exec 进来了
/usr/bin/mysqld_safe --datadir='/var/lib/mysql' &
# 设置root 密码
mysqladmin -u root password "root"
3.3.1 Client inspection
# 客户端登录,注意-p 后面直接跟密码不能有空格
mysql -u root -p"root"
Use the built-in mysql
database to test SQL
statements
use mysql
select count(*) from user;
exit
Or write the test content together
# 创建测试文件
cd /tmp
cat > test.sql << EOF
use mysql
select count(*) from user;
exit
EOF
# 使用管道符传给mysql 客户端执行
cat test.sql | mysql -u root -proot
In order to facilitate the script to run, such as automatic backup of scheduled tasks, we can also configure~/.my.cnf
cat > ~/.my.cnf << EOF
[client]
host=localhost
port=3306
user='root'
password='root'
[mysql]
database='mysql'
EOF
Later, use mysql
, mysqldump
these commands do not need to enter a user name and password.
3.3.2 PHP connection check
Create php
test pagevi /www/mysql.php
<?php
$mysql_conf = array(
'host' => '127.0.0.1:3306',
'db' => 'mysql',
'db_user' => 'root',
'db_pwd' => 'root',
);
$mysqli = @new mysqli($mysql_conf['host'], $mysql_conf['db_user'], $mysql_conf['db_pwd']);
if ($mysqli->connect_errno) {
die("could not connect to the database:\n" . $mysqli->connect_error);
}
$mysqli->query("set names 'utf8';");
$select_db = $mysqli->select_db($mysql_conf['db']);
if (!$select_db) {
die("could not connect to the db:\n" . $mysqli->error);
}
$sql = "select count(*) from user;";
$res = $mysqli->query($sql);
if (!$res) {
die("sql error:\n" . $mysqli->error);
}
while ($row = $res->fetch_assoc()) {
var_dump($row);
}
$res->free();
$mysqli->close();
?>
Open the browser in the host machine to access localhost:8080/mysql.php
, just display array(1) { ["count(*)"]=> string(1) "6" }
.
4 OpenRC
4.1 Installation
# 安装openrc 主要用于控制后台服务
apk add openrc
4.2 Configuration
# 让openrc 加载所需的依赖,否则一直WARNING: xxxxx is already started,却没在运行
/sbin/openrc
# rc-status -a # 效果同上,目的就是启动openrc 让其加载运行环境
# 执行service nginx status 会提示要创建该文件
touch /run/openrc/softlevel
# 告诉openrc 它运行在虚拟容器中,'lxc' 在/etc/rc.conf 中有注释
sed -i 's/#rc_sys=""/rc_sys="lxc"/g' /etc/rc.conf
# 告诉openrc 网络已经可以工作了,因为环回口不会down,它就会觉得网络一直可用
echo 'rc_provide="loopback net"' >> /etc/rc.conf
# 不记录日志
sed -i 's/^#\(rc_logger="YES"\)$/\1/' /etc/rc.conf
# 不尝试获取tty 设备,否则运行容器时执行/sbin/init 会一直报tty 错误
sed -i '/tty/d' /etc/inittab
# 不设置主机名,注释掉对应设置
sed -i 's/hostname $opts/# hostname $opts/g' /etc/init.d/hostname
# 不加载tmpfs
sed -i 's/mount -t tmpfs/# mount -t tmpfs/g' /lib/rc/sh/init.sh
# 不运行cgroup,避免service start xxxxx 时read only 错误
sed -i 's/cgroup_add_service /# cgroup_add_service /g' /lib/rc/sh/openrc-run.sh
4.3 Inspection
Take nginx
service as an example
# 查看nginx 状态
service nginx status
# 启动nginx
service nginx start
# 停止nginx
service nginx stop
# 重启nginx
service nginx restart
Note: If nginx
there is a problem with the configuration file, the above command will be abnormal, for example, the display nginx
status is crashed
but the browser can still access it.
Use nginx -s stop
to stop, then only use nginx
this command to start, service nginx start
do nothing, service nginx status
it will only display it crashed
.
Set the service to start
# 设置开机启动的服务
rc-update add nginx default
rc-update add php-fpm default
rc-update add mariadb default
# 退出docker 容器
exit
# 重启docker 容器
docker restart mnp5
# 重新进入容器
docker exec -it mnp5 sh
# 查看服务状态
rc-status -a
# 查看所有进程
ps -ef
Cleanup
Close delete container
# 清理apk 的缓存
rm -rf /var/cache/apk/*
rm -rf /tmp/*
# 删除容器这些东西也会被一并清除,可略过
# 退出容器mnp5
exit
# 停止容器
docker stop mnp5
# 删除容器
docker rm mnp5
Docker deployment
Make a container image and run the test
Dockerfile
https://github.com/suzhi82/mnp5
https://github.com/suzhi82/mnp5/blob/master/Dockerfile
Create run verification
Create mirror
# 获取Dockerfile 及相关文件
git clone https://github.com/suzhi82/mnp5.git
# 创建镜像
docker build --no-cache . -t mnp5
Run container
# 运行镜像
docker run --name mnp5 -p 8888:80 -d mnp5
Authentication service
# 进入容器
docker exec -it mnp5 bash
# 进入后应该可以看到来自/etc/motd 的提示
Visit localhost:8888
to see the demo page.
DockerHub
Another way to get the Docker
image
docker pull suzhi82/mnp5
# 或者直接运行
docker run --name mnp5 -p 8888:80 -d suzhi82/mnp5
Reference documents
alpine Nginx with PHP
alpine MariaDB
alpine MariaDB GitHub
alpine OpenRC
How to enable and start services on Alpine Linux