当前位置:首页 > 技术 > 正文内容

容器指南之自定义LNMP容器镜像

Lotus2022-12-08 13:28技术

1.简介

在Linux 环境中最常用的组件应该属于 LNMP 组合(Linux + Nginx + Mysql +PHP),当然,随着Go、Rust语言的普及,生产环境有更多的组合配置。但是 Nginx 的Web端和MySQL 的数据库端还是主力配置。

受 Nginx、MySQL 和 PHP 多版本和多配置文件的影响,在生产或测试环境要保持各组件版本和对应的配置文件(特别是安全配置)统一需要花费大量的时间和成本。

使用容器技术定制适合自己环境的组件镜像,需要使用的时候无需复杂和长时间的配置调整就能在1分钟以内提供标准的经过验证的LNMP 环境。

Nginx 配置指南 ​​​​https://blog.51cto.com/waringid/1438852​

容器指南之第一个容器     ​​https://blog.51cto.com/waringid/5904849​

容器指南之容器架构及常用指令   ​​https://blog.51cto.com/waringid/5913145​

容器指南之日常运维  ​​https://blog.51cto.com/waringid/5914178​

Docker For Windows 安装配置及常用维护  ​​https://blog.51cto.com/waringid/5917666​

2.LNMP 环境介绍

1、基于 PHP7.4.28 版本,添加 PHP-GD 扩展

2、Nginx 配置最新版本

3、Mysql 使用 Mariadb10版本

2.1.自定义 php 环境

sudo mkdir /opt/php
sudo chown docker /opt/php
cat > /opt/php/Dockfile << EOF
FROM php:7.4.28-fpm-alpine3.15

RUN set -x \
&& echo "http://mirrors.huaweicloud.com/alpine/latest-stable/main/" > /etc/apk/repositories \
&& echo "http://mirrors.huaweicloud.com/alpine/latest-stable/community/" >> /etc/apk/repositories \
&& apk update \
&& apk add --no-cache tzdata \
&& cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone \
&& apk del tzdata \
&& apk add --no-cache graphviz zlib-dev libpng-dev libxml2-dev zip libzip-dev \
&& docker-php-ext-configure zip \
&& docker-php-ext-install gd pdo_mysql soap mysqli zip
EOF
docker build -t php-fpm:7.4 .
docker images
sudo docker save -o /opt/images/php-fpm-7.4.28.tar php-fpm:7.4

容器指南之自定义LNMP容器镜像_docker

容器指南之自定义LNMP容器镜像_mysql_02

2.2.配置 LNMP 环境

sudo mkdir /opt/lnmp
sudo chown docker /opt/lnmp
cat > /opt/lnmp/docker-compose.yml << EOF
version: '2.1'
services:
db:
image: mariadb:10.5
container_name: mysql
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=password # Root password of MySQL -- must be changed
- MYSQL_LOG_CONSOLE=true
volumes:
- /opt/lnmp/mysql-data:/var/lib/mysql # Volume of MySQL (directory for persistent storage) and mount point in container -- can be changed (not advised)
networks:
lnmp-net:
ipv4_address: 172.18.0.3

nginx:
image: nginx
container_name: nginx
ports:
- "80:80"
volumes:
- /opt/lnmp/nginx/www:/usr/share/nginx/html
- /opt/lnmp/nginx/conf:/etc/nginx/conf
- /opt/lnmp/nginx/conf.d:/etc/nginx/conf.d
- /opt/lnmp/nginx/logs:/var/log/nginx

networks: lnmp-net:
ipv4_address: 172.18.0.2

php:
image: php-fpm:7.4
container_name: php
volumes:
- /opt/lnmp/nginx/www:/www
networks:
lnmp-net:
ipv4_address: 172.18.0.3

networks:
ipam:
config:
- subnet: "172.18.0.0/24"
EOF

cat > /opt/lnmp/nginx/conf.d/php.conf << EOF
server {
listen 80;
server_name localhost;
client_max_body_size 1000m;

location / {
root /usr/share/nginx/html;
index index.html index.htm index.php;
if ( !-f $request_filename ) {
rewrite ^/login$ /login.php last;
rewrite ^/register$ /register.php last;
rewrite ^/search$ /search.php last;
rewrite ^/discount/student$ /discount.php?u=d last;
rewrite ^/discount/teacher$ /discount.php?u=t last;
# rewrite ^/admin.php$ /404.html break;
rewrite ^/(.*)$ /index.php/$1 last;
}
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}

location ~ \.php(.*)$ {
root /www;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_param SCRIPT_FILENAME /www$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
include fastcgi_params;
}
}
EOF
cat > /opt/lnmp/nginx/www/index.php << EOF
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
echo '<h1 style="text-align: center;">欢迎使用DNMP!</h1>';
echo '<h2>版本信息</h2>';
echo '<ul>';
echo '<li>PHP版本:', PHP_VERSION, '</li>';
echo '<li>Nginx版本:', $_SERVER['SERVER_SOFTWARE'], '</li>';
echo '<li>MySQL服务器版本:', getMysqlVersion(), '</li>';
echo '<li>Redis服务器版本:', getRedisVersion(), '</li>';
echo '<li>MongoDB服务器版本:', getMongoVersion(), '</li>';
echo '</ul>';
echo '<h2>已安装扩展</h2>';
printExtensions();
/**
* * 获取MySQL版本
* */
function getMysqlVersion()
{
if (extension_loaded('PDO_MYSQL')) {
try {
$dbh = new PDO('mysql:host=mysql;dbname=mysql', 'root', '123456');
$sth = $dbh->query('SELECT VERSION() as version');
$info = $sth->fetch();
} catch (PDOException $e) {
return $e->getMessage();
}
return $info['version'];
} else {
return 'PDO_MYSQL 扩展未安装 ×';
}
}

/**
* * 获取Redis版本
* */
function getRedisVersion()
{
if (extension_loaded('redis')) {
try {
$redis = new Redis();
$redis->connect('redis', 6379);
$info = $redis->info();
return $info['redis_version'];
} catch (Exception $e) {
return $e->getMessage();
}
} else {
return 'Redis 扩展未安装 ×';
}
}

/**
* * 获取MongoDB版本
* */
function getMongoVersion()
{
if (extension_loaded('mongodb')) {
try {
$manager = new MongoDB\Driver\Manager('mongodb://root:123456@mongodb:27017');
$command = new MongoDB\Driver\Command(array('serverStatus'=>true));
$cursor = $manager->executeCommand('admin', $command);
return $cursor->toArray()[0]->version;
} catch (Exception $e) {
return $e->getMessage();
}
} else {
return 'MongoDB 扩展未安装 ×';
}
}

/**
* * 获取已安装扩展列表
* */
function printExtensions()
{
echo '<ol>';
foreach (get_loaded_extensions() as $i => $name) {
echo "<li>", $name, '=', phpversion($name), '</li>';
}
}
echo '</ol>';
}
EOF
cd /opt/lnmp
docker-compose up

 

容器指南之自定义LNMP容器镜像_自定义LNMP镜像_03

2.3.安装扩展

默认php镜像中提供的扩展比较少,缺少诸如mysql、gd2等常用的扩展,这样我们就需要自己安装并启用扩展。

首先进入到php容器,用php -m命令查看本地有什么扩展。

可以使用docker-php-ext-install命令来安装扩展。

docker-php-ext-install mysql

扩展安装好之后就可以在php.ini中启用。我们从phpinfo中可以看到,容器环境下默认的php.ini没有启用,可以从/usr/local/etc/php下将php.ini-development拷贝为php.ini。通过修改php.ini中配置,启用自己需要的扩展。

下面是几个扩展安装的命令,供参考。

  • docker-php-ext-source 在容器中创建一个/usr/src/php目录
  • docker-php-ext-enable启用PHP扩展,省去我们手工编辑php.ini的过程
  • docker-php-ext-install安装并启用PHP扩展
  • docker-php-ext-configure经常与docker-php-ext-install搭配,在需要自定义扩展的配置时使用

2.4.单独运行命令行

如果仅需要在命令行下运行 php 命令,可以使用如下方式

# 将当前目录挂载到 /tmp 目录,执行 php 命令,结束后退出

docker run -it --rm -v $PWD:/tmp -w /tmp php-fpm:7.4 php test.php

3.备份和恢复数据库

docker exec -it seafile-mysql mysqldump  -uroot --opt ccnet_db > ccnet_db.sql
docker exec -it seafile-mysql mysqldump -uroot --opt seafile_db > seafile_db.sql
docker exec -it seafile-mysql mysqldump -uroot --opt seahub_db > seahub_db.sql

docker cp /opt/seafile-backup/databases/ccnet_db.sql seafile-mysql:/tmp/ccnet_db.sql
docker cp /opt/seafile-backup/databases/seafile_db.sql seafile-mysql:/tmp/seafile_db.sql
docker cp /opt/seafile-backup/databases/seahub_db.sql seafile-mysql:/tmp/seahub_db.sql

docker exec -it seafile-mysql /bin/sh -c "mysql -uroot ccnet_db < /tmp/ccnet_db.sql"
docker exec -it seafile-mysql /bin/sh -c "mysql -uroot seafile_db < /tmp/seafile_db.sql"
docker exec -it seafile-mysql /bin/sh -c "mysql -uroot seahub_db < /tmp/seahub_db.sql"

4.常见问题

mysql 容器

容器指南之自定义LNMP容器镜像_docker_04

解决方法:

security_opt:
- seccomp:unconfined

原文链接

扫描二维码推送至手机访问。

版权声明:本文来源于网络,仅供学习,如侵权请联系站长删除。

本文链接:https://news.layui.org.cn/post/1108.html

分享给朋友:

“容器指南之自定义LNMP容器镜像” 的相关文章

前端三剑客快速入门(二)

前言 本文书接上回,继续css的知识,序号就重新开始了。上篇内容:前端三剑客快速入门(一) CSS 盒子模型 盒子模型属性: border外框 margin外边距 padding内边距 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <me...

【大话云原生】煮饺子与docker、kubernetes之间的关系

文章开始之前,我给大家推荐一个人工智能学习网站,首先说我之前是完全不涉及人工智能领域的,但是我尽然看懂了,以后老哥我就要参与人工智能了。如果你也想学习,点击跳转到网站 云原生的概念最近非常火爆,企业落地云原生的愿望也越发强烈。看过很多关于云原生的文章,要么云山雾罩,要么曲高和寡。 所以笔者就有了写《大话云原生》系列文章的想法,期望用最通俗、简单的语言说明白云原生生态系统内的组成及应用关系。那么,...

一个故事看懂CPU的SIMD技术

好久不见,我叫阿Q,是CPU一号车间的员工。我所在的CPU有8个车间,也就是8个核心,咱们每个核心都可以同时执行两个线程,就是8核16线程,那速度杠杠滴。 我所在的一号车间,除了负责执行指令的我,还有负责读取指令的小A,负责指令译码的小胖和负责结果回写的老K,我们几个各司其职,一起完成执行程序的工作。 一个简单的循环 那天,我们遇到了一段代码: void array_add(int data[]...

谣言检测()——《Debunking Rumors on Twitter with Tree Transformer》

论文信息 论文标题:Debunking Rumors on Twitter with Tree Transformer论文作者:Jing Ma、Wei Gao论文来源:2020,COLING论文地址:download 论文代码:download 1 Introduction   出发点:Existing conversation-based techniques for rumor...

[CG从零开始] 6. 加载一个柴犬模型学习UV贴图

在第 5 篇文章中,我们成功加载了 fbx 模型,并且做了 MVP 变换,将立方体按照透视投影渲染了出来。但是当时只是随机给顶点颜色,并且默认 fbx 文件里只有一个 mesh,这次我们来加载一个柴犬模型,并且给模型贴图,模型可以从 sketchfab 下载。 本文没有涉及到理论解释,更多的是代码实践。 完整代码在 https://github.com/MangoWAY/CGLearner/tr...

Python Scala中使用def语句定义方法的详细过程

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于Scala中使用def语句定义方法的详细过程,Scala的方法是类的一部分,而函数是一个对象可以赋值给一个变量,下面一起来看一下,希望对大家有帮助。 程序员必备接口测试调试工具:立即使用 Apipost = Postman + Swagger + Mock + Jmeter Api设计、调试、文档、自动化测试工具...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。