菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
11
0

docker-compose 搭建 dnmp 总结

原创
05/13 14:22
阅读数 563

说明

从零开始写一份dnmp环境的docker-compose.yml(由于redis比较常用,也包括进来)。总体设计示意图:

docker-compose搭建dnmp总结
网络分配上,让要直接通讯的容器同属于一个网络,不直接通讯的容器属于不同的网络,这样实现网络的隔离,如上图所示,Nginx和PHP-FPM同属于网络A,PHP-FPM、Redis和MySQL同属于网络B。数据存放上,将项目代码存放在宿主机上的folderA,同时创建数据卷映射到Nginx和PHP-FPM中。

目录规划如下:

├─conf  # 1. 配置文件目录
│  ├─mysql  # mysql配置文件目录,下同
│  │      my.cnf  # 事先准备好的默认配置文件,下同
│  ├─nginx
│  │  │  nginx.conf
│  │  └─conf.d
│  │          default.conf
│  ├─php
│  │  │  php.ini
│  │  └─conf.d
│  ├─redis
│  │      redis.conf
│  └─supervisor
│          supervisord.conf
├─data  # 2. 数据库数据、项目代码目录,可按mysql、php等目录划分
├─dockerfiles  # 3. 存放Dockerfile的目录
│      Dockerfile.php73
├─log  # 4. 日志目录,可按mysql、php等目录划分
└─ssl # 5. https证书文件存放目录

docker-compose.yml文件大概结构如下:

docker-compose搭建dnmp总结

接下来我们逐个服务编写配置、调试和解决遇到的问题。

注:宿主机系统为 Ubuntu 18,所有命令都是用非root账号运行

Redis

配置

redis:
        image: redis:latest  # 使用最新镜像
        volumes:
            - ./data/redis:/data  # 数据目录
            - ./conf/redis/redis.conf:/etc/redis/redis.conf  # 配置文件
        networks:
            - mysql
        ports:
            - "6379:6379"
        sysctls:
            - net.core.somaxconn=1024
        command: >  # 注意多个命令时的写法
            bash -c "echo 'vm.overcommit_memory = 1' >> /etc/sysctl.conf
            && redis-server /etc/redis/redis.conf --appendonly yes"

遇到的问题

docker-compose.yml文件所在目录下,运行:docker-compose up redis,有如下错误信息:

  • 报错:WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.

    解决:如上面的配置所示,添加:sysctls: - net.core.somaxconn=1024

  • 报错:WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.

    解决:如配置所示,command键中添加:echo 'vm.overcommit_memory = 1' >> /etc/sysctl.conf,该设置依赖宿主机,所以同时在宿主机中也要运行该命令。

  • 报错:WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.

    解决:宿主机终端中依次运行:

    echo never > /sys/kernel/mm/transparent_hugepage/enabled
    echo never > /sys/kernel/mm/transparent_hugepage/defrag

MySQL

配置

mysql:
        image: mysql:latest # 使用最新的版本
        volumes:
            - ./data/mysql:/var/lib/mysql  # 数据目录
            - ./conf/mysql/my.cnf:/etc/mysql/my.cnf # 配置文件
        networks:
            - mysql
        ports:
            - "3306:3306"
        environment:
            - MYSQL_ROOT_PASSWORD=root  # 密码设置,注意改成自己的密码
        # 设置密码加密驱动,原因参见:https://lmonkey.com/articles/34823
        command: --default-authentication-plugin=mysql_native_password 

遇到的问题

  • mysqld: Can't create/write to file '/var/lib/mysql/is_writable' (Errcode: 13 - Permission denied)

    解决:这个问题网上给出的方法是:将运行mysql的用户设置成当前的用户,比如,添加配置:user: "1000:50", 或者user:"999:999", 但这用户1000或999是怎么获取的呢?于是,我找到更接近本质的方法是先获取当前用户,然后再添加到配置,比如,添加配置,user: ${CURRENT_UID},然后每次运行时,都要在宿主机上先运行:CURRENT_UID=$(id -u):$(id -g)
    总觉得这样的方法不太完美,思来想去,决定先在宿主机查一下,当前运行mysql的用户,终端运行top命令,发现其运行的用户是999,运行cat /etc/group查看用户所属的组,发现最后有一行docker:x:999,999用户是属于docker组的,于是,将我当前宿主机使用的用户(ubuntu)也添加到docker组,即运行:sudo usermod -aG docker ubuntu。随后,再运行docker-compose up mysql就不再有这个报错了。(记得将之前添加的user: ${CURRENT_UID}配置删掉)

Nginx

配置

 nginx:
        image: nginx:alpine  # 使用Alpine Linux,其内核比较小,大大较少镜像体积
        volumes:
            - ../project:/var/www/html  # 项目源码所在目录
            - ./conf/nginx/nginx.conf:/etc/nginx/nginx.conf:ro # 主配置,设置read-only
            - ./conf/nginx/conf.d:/etc/nginx/conf.d:ro
            - ./log/nginx:/var/log/nignx
            - ./ssl:/etc/nginx/ssl
        networks:
            - nginx
        ports:
            - "80:80"
            - "443:443"

php-fpm

这一部分比较复杂,需要安装一些扩展,编译出新的镜像,所以使用到了Dockerfile文件。

配置

php-fpm73:
        build:
            context: .  # 构建镜像的上下文
            dockerfile: dockerfiles/Dockerfile.php73 # 指定Dockerfile文件,根据上下文找到地址
        volumes:
            - ../project:/var/www/html   # 项目源码所在目录
            - ./conf/php:/usr/local/etc/php
            - ./conf/php/conf.d:/usr/local/etc/php/conf.d
            - ./conf/supervisor:/etc/supervisor/conf.d
        networks:
            - mysql
            - nginx
        ports:
            - "9000:9000"

遇到的问题

  • 安装Laravel项目时,发现提示gd扩展不存在
    解决:之前在其他机子运行时是直接可用的,进入php-fpm的容器,运行php --ini,输出:
    Configuration File (php.ini) Path: /usr/local/etc/php
    Loaded Configuration File:         /usr/local/etc/php/php.ini
    Scan for additional .ini files in: /usr/local/etc/php/conf.d
    Additional .ini files parsed:      (none)

    /usr/local/etc/php/conf.d中并没有额外的配置,我在另外的主机运行,是有额外配置的:

    Loaded Configuration File:         /usr/local/etc/php/php.ini
    Scan for additional .ini files in: /usr/local/etc/php/conf.d
    Additional .ini files parsed:      /usr/local/etc/php/conf.d/docker-php-ext-gd.ini,
    /usr/local/etc/php/conf.d/docker-php-ext-imagick.ini,
    /usr/local/etc/php/conf.d/docker-php-ext-mysqli.ini,
    /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini,
    /usr/local/etc/php/conf.d/docker-php-ext-pcntl.ini,
    /usr/local/etc/php/conf.d/docker-php-ext-pdo_mysql.ini,
    /usr/local/etc/php/conf.d/docker-php-ext-redis.ini,
    /usr/local/etc/php/conf.d/docker-php-ext-sodium.ini,
    /usr/local/etc/php/conf.d/docker-php-ext-swoole.ini,
    /usr/local/etc/php/conf.d/docker-php-ext-zip.ini

    调整配置,重新编译,还是不行,最后只能手动修改php.ini,添加:

    extension=gd.so

    最后,顺利安装Laravel项目。

完整的配置文件和常用命令

所有配置参见:https://github.com/HubQin/dnmp

运行git clone https://github.com/HubQin/dnmp.git,下载配置后,切换到dnmp目录,运行:docker-compose up -d即可开启dnmp环境,注意在dnmp文件夹外部会生成一个project目录(如果没有的话),是用来方项目代码的。

docker-compose常用的命令有:

  • docker-compose up -d 后台运行docker-compose.yml 配置的所有服务
  • 进入容器,比如,进入php-fpm73容器,方式A:docker container exec -it dnmp_php-fpm73_1 /bin/bashdnmp_php-fpm73_1为容器名称,可以通过docker ps查看;方式B:docker-compose exec php-fpm73 bashphp-fpm73为服务名称(docker-compose.yml 中配置的名称),注意该命令需在docker-compose.yml 所在目录下运行或者指定docker-compose.yml 所在位置。
  • 重新编译镜像,docker-compose build php-fpm73
  • 指定后台启动php-fpm73服务:docker-compose up -d php-fpm73
  • 停止所有服务:docker-compose stop
  • 停止所有服务并删除容器:docker-compose down

发表评论

0/200
11 点赞
0 评论
收藏