简单使用 Docker 配置开发环境(mac+php)

前言

  • 搭建开发环境是一个开发者必备的技能,但是重复的搭建各种开发环境,依然是一件很无趣且浪费时间的事情。
  • 以前的解决方案通常是虚拟机或者一些集成工具,它们能很好的解决重复搭建相同开发环境的问题。
  • 同时它们也有着一些缺陷,比如虚拟机过于笨重,集成工具功能比较固定单一。
  • docker 等虚拟容器技术的出现,让开始构建多样的开发环境成为可能。

基础需求

第一步 clone docker-compose 脚本,复制配置文件

# 克隆脚本
git clone https://github.com/snowlyg/dnmp
#复制配置文件
copy docker-compose.sample.yml docker-compose.yml

根据自己需要的服务,修改配置文件解开或者加上对应的注释代码

  • php 基础开发环境nginx + mysql + redis 如下
version: "3"
services:
  nginx:
    build:
      context: ./services/nginx
      args:
        NGINX_VERSION: 1.15.7-alpine
        CONTAINER_PACKAGE_URL: mirrors.aliyun.com
        NGINX_INSTALL_APPS: ""
    container_name: nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./www:/www/:rw
      - ./services/nginx/ssl:/ssl:rw
      - ./services/nginx/conf.d:/etc/nginx/conf.d/:rw
      - ./services/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./services/nginx/fastcgi-php.conf:/etc/nginx/fastcgi-php.conf:ro
      - ./services/nginx/fastcgi_params:/etc/nginx/fastcgi_params:ro
      - ./logs/nginx:/var/log/nginx/:rw
    environment:
      TZ: "Asia/Shanghai"
    restart: always
    networks:
      - default

  php:
    build:
      context: ./services/php
      args:
        PHP_VERSION: php:7.3-fpm-alpine
        CONTAINER_PACKAGE_URL: mirrors.aliyun.com
        PHP_EXTENSIONS: "pdo_mysql,mysqli,mbstring,gd,curl,opcache,soap,amqp,bcmath,pcntl,redis,xdebug"
        TZ: "Asia/Shanghai"
    container_name: php
    expose:
      - 9501
    extra_hosts:
      - "www.site1.com:172.17.0.1"
    volumes:
      - ./www:/www/:rw
      - ./services/php/php.ini:/usr/local/etc/php/php.ini:ro
      - ./services/php/php-fpm.conf:/usr/local/etc/php-fpm.d/www.conf:rw
      - ./logs/php:/var/log/php
      - ./data/composer:/tmp/composer
    restart: always
    cap_add:
      - SYS_PTRACE
    networks:
      - default

#  php56:
#    build:
#      context: ./services/php
#      args:
#        PHP_VERSION: php:5.6.40-fpm-alpine
#        CONTAINER_PACKAGE_URL: mirrors.aliyun.com
#        PHP_EXTENSIONS: "pdo_mysql,mysqli,mbstring,gd,curl,opcache"
#        TZ: "Asia/Shanghai"
#    container_name: php56
#    expose:
#      - 9501
#    volumes:
#      - ./www:/www/:rw
#      - ./services/php/php.ini:/usr/local/etc/php/php.ini:ro
#      - ./services/php/php-fpm.conf:/usr/local/etc/php-fpm.d/www.conf:rw
#      - ./logs/php:/var/log/php
#      - ./data/composer:/tmp/composer
#    restart: always
#    cap_add:
#      - SYS_PTRACE
#    networks:
#      - default

  #  php54:
  #    build:
  #      context: ./services/php54
  #      args:
  #        PHP_VERSION: php:5.4.45-fpm
  #        CONTAINER_PACKAGE_URL: mirrors.aliyun.com
  #        PHP_EXTENSIONS: "pdo_mysql,mysqli,mbstring,gd,curl,opcache"
  #        TZ: "Asia/Shanghai"
  #    container_name: php54
  #    volumes:
  #      - ./www:/www/:rw
  #      - ./services/php54/php.ini:/usr/local/etc/php/php.ini:ro
  #      - ./services/php54/php-fpm.conf:/usr/local/etc/php-fpm.d/www.conf:rw
  #      - ./logs/php:/var/log/php
  #      - ./data/composer:/tmp/composer
  #    restart: always
  #    cap_add:
  #      - SYS_PTRACE
  #    networks:
  #      - default

  mysql:
   image: mysql:8.0.13
   container_name: mysql
   ports:
     - "3306:3306"
   volumes:
     - ./services/mysql/mysql.cnf:/etc/mysql/conf.d/mysql.cnf:ro
     - ./data/mysql:/var/lib/mysql/:rw
   restart: always
   networks:
     - default
   environment:
     MYSQL_ROOT_PASSWORD: "123456"
     TZ: "Asia/Shanghai"

  # mysql5:
  #   image: mysql:5.7.28
  #   container_name: mysql5
  #   ports:
  #     - "3305:3306"
  #   volumes:
  #     - ./services/mysql5/mysql.cnf:/etc/mysql/conf.d/mysql.cnf:ro
  #     - ./data/mysql5:/var/lib/mysql/:rw
  #   restart: always
  #   networks:
  #     - default
  #   environment:
  #     MYSQL_ROOT_PASSWORD: "123456"
  #     TZ: "Asia/Shanghai"

  #  openresty:
  #    image:  openresty/openresty:alpine
  #    container_name: openresty
  #    ports:
  #       - "80:80"
  #       - "443:443"
  #    volumes:
  #       - ./www:/www/:rw
  #       - ./services/openresty/conf.d:/etc/nginx/conf.d/:ro
  #       - ./services/openresty/openresty.conf:/ssl:rw
  #       - ./services/openresty/fastcgi-php.conf:/usr/local/openresty/nginx/conf/nginx.conf:ro
  #       - ./services/openresty/fastcgi_params:/usr/local/openresty/nginx/conf/fastcgi-php.conf:ro
  #       - ./services/openresty/ssl:/usr/local/openresty/nginx/conf/fastcgi_params:ro
  #       - ./logs/nginx:/var/log/nginx/:rw
  #    environment:
  #      TZ: "Asia/Shanghai"
  #    networks:
  #      - default

  redis:
    image: redis:5.0.3-alpine
    container_name: redis
    ports:
      - "6379:6379"
    volumes:
      - ./services/redis/redis.conf:/etc/redis.conf:ro
      - ./data/redis:/data/:rw
    restart: always
    entrypoint: ["redis-server", "/etc/redis.conf"]
    environment:
      TZ: "Asia/Shanghai"
    networks:
      - default

  #  memcached:
  #    image: memcached:alpine
  #    container_name: memcached
  #    ports:
  #      - "11211:11211"
  #    environment:
  #       MEMCACHED_CACHE_SIZE: "128"
  #    networks:
  #      - default

  # rabbitmq:
  #   image: rabbitmq:management
  #   container_name: rabbitmq
  #   restart: always
  #   ports:
  #     - "5672:5672"
  #     - "15672:15672"
  #   environment:
  #      TZ: "Asia/Shanghai"
  #      RABBITMQ_DEFAULT_USER: "myuser"
  #      RABBITMQ_DEFAULT_PASS: "mypass"
  #   networks:
  #         - default

  # phpmyadmin:
  #  image: phpmyadmin/phpmyadmin:latest
  #  container_name: phpmyadmin
  #  ports:
  #    - "8080:80"
  #  volumes:
  #    - ./services/phpmyadmin/config.user.inc.php:/etc/phpmyadmin/config.user.inc.php:ro
  #    - ./services/phpmyadmin/php-phpmyadmin.ini:/usr/local/etc/php/conf.d/php-phpmyadmin.ini:ro
  #  networks:
  #    - default
  #  environment:
  #    - PMA_HOST=mysql
  #    - PMA_PORT=3306
  #    - TZ=Asia/Shanghai

  # phpredisadmin:
  #  image: erikdubbelboer/phpredisadmin:latest
  #  container_name: phpredisadmin
  #  ports:
  #    - "${REDISMYADMIN_HOST_PORT}:80"
  #  networks:
  #    - default
  #  environment:
  #    - REDIS_1_HOST=redis
  #    - REDIS_1_PORT=6379
  #    - TZ=Asia/Shanghai

  # mongodb:
  #  image: mongo:4.1
  #  container_name: mongodb
  #  environment:
  #      MONGO_INITDB_ROOT_USERNAME: "root"
  #      MONGO_INITDB_ROOT_PASSWORD: "123456"
  #      TZ: "Asia/Shanghai"
  #  volumes:
  #    - ./data/mongo:/data/db:rw
  #    - ./data/mongo_key:/mongo:rw
  #  ports:
  #     - "27017:27017"
  #  networks:
  #     - default
  #  command:
  #     --auth

  #  adminmongo:
  #    image: mrvautin/adminmongo
  #    container_name: adminmongo
  #    ports:
  #      - "1234:1234"
  #    environment:
  #      - HOST=0.0.0.0
  #      - DB_HOST=mongodb
  #      - DB_PORT=27017
  #    networks:
  #      - default

  # elasticsearch:
  #  build:
  #    context: ./services/elasticsearch
  #    args:
  #      ELASTICSEARCH_VERSION: 7.1.1
  #      ELASTICSEARCH_PLUGINS: ""
  #  container_name: elasticsearch
  #  environment:
  #    - TZ=Asia/Shanghai
  #    - discovery.type=single-node
  #    - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
  #  volumes:
  #    - ./data/esdata:/usr/share/elasticsearch/data
  #    - /services/elasticsearch/elasticsearch.yml:/usr/share/elasticsearch/elasticsearch.yml
  #  hostname: elasticsearch
  #  restart: always
  #  ports:
  #    - "9200:9200"
  #    - "9300:9300"

#  kibana:
#    image: kibana:7.1.1
#    container_name: kibana
#    environment:
#      TZ: "Asia/Shanghai"
#      elasticsearch.hosts: http://elasticsearch:9200
#      I18N_LOCALE: "zh-CN"
#    hostname: kibana
#    depends_on:
#      - elasticsearch
#    restart: always
#    ports:
#      - "5601:5601"

#  logstash:
#    image: logstash:7.1.1
#    container_name: logstash
#    hostname: logstash
#    restart: always
#    depends_on:
#      - elasticsearch
#    environment:
#      TZ: "Asia/Shanghai"
#    ports:
#      - "9600:9600"
#      - "5044:5044"


networks:
  default:

在脚本根目录执行 docker-compose 命令,构建环境

  • 如果本机安装了对应的服务,比如 apache,nginx,mysql 等,会导致对应80,3306 等端口别占用。
  • 需要修改前面的配置的端口映射关系项
# 修改为,前面的端口是本机端口,后面的是容器内的端口。
# 这个设置表示将 本机端口映射到容器的80端口
# 后面访问的时候也需要使用 83 端口,比如 http://localhost:83s
ports:
  - "83:80" 
  # 构建本启动脚本未注释部分的服务,并在守护对应服务
  docker-compose up -d
  # 如果只启动部分服务,比如 php
  docker-compose up -d php
  # 或者 php mysql
  docker-compose up -d php mysql

查看对应服务是否正常启动

  • 可以直接在面板看 apps

  • 或者使用命令行 docker ps 查看 apps-cli

  • 可以看到对应服务的名称,状态,创建时间和对应的端口

部署一个应用到这个 docker 搭建的 php 环境中

#进入 nginx 配置目录
cd services/nginx/conf.d/
# 新建一个配置文件 loclhost.conf
server {
  listen 80;
  server_name localhost;
  root /www;

  #add_header X-Frame-Options "SAMEORIGIN";
  #add_header X-XSS-Protection "1; mode=block";
  #add_header X-Content-Type-Options "nosniff";

  index index.html index.htm index.php;

  charset utf-8;

  location / {
    #try_files $uri $uri/ /index.php?$query_string;
    if (!-e $request_filename) {
      rewrite  ^(.*)$  /index.php?s=/$1  last;
    }
  }

  location = /favicon.ico { access_log off; log_not_found off; }
  location = /robots.txt  { access_log off; log_not_found off; }

  error_page 404 /index.php;

  location ~ \.php$ {
    fastcgi_pass  php:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
    include fastcgi_params;
  }

  location ~ /\.(?!well-known).* {
    deny all;
  }
}
# 注意 location ~\.php$ {} 里面, fastcgi_pass 的值是 php:9000 不是通常的 127.0.0.1,至于原理后面会提到

# 新建一个 index.html 文件到 www/ 目录下,再访问 http://localhost 就能看到 index.html 里面的内容了。 

容易踩坑点

  • 部署正式项目的时候,配置 mysql ,redis 的服务地址配置的时候不能使用常规的 localhost 或者 127.0.0.1。
  • 因为 php,mysql,redis,nginx 都部署再相对隔离的不同 docker 容器中,就如同把它们安装再了不同机器上一样。
  • 要在容器中访问其他容器 ,需要使用它们的容器名称,也是它们的网络地址别名,比如 mysql,php 等等。
  • 所以前面配置 nginx 设置的时候 location ~.php$ {} 里面, fastcgi_pass 的值是 php:9000 不是通常的 127.0.0.1