Home » Code » Linux » docker构建开发环境-详细篇

docker构建开发环境-详细篇

环境安装参考前篇。前篇写得不是很详细,过后就忘,再来一次!

安装nginx

编写docker-compose.yml,最简单的,启动一个nginx服务,容器命名为huanbao-nginx,内部监听80端口,映射到外部物理机的7777端口。

version: "3.1"
services:
    nginx:
      image: nginx
      container_name: huanbao-nginx
      ports:
       - "7777:80"

image: nginx,相当于image: nginx:latest,表示使用nginx仓库中的latest这个版本。启动后查看当前启动的服务:

执行docker exec -it huanbao-nginx bash,进入容器内部。

[root@iZuf6jcwx7sfb1h6ayjq99Z docker-demo]# docker exec -it huanbao-nginx bash
root@dc7f2ee539a6:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@dc7f2ee539a6:/# /usr/sbin/nginx -V
nginx version: nginx/1.13.5
built by gcc 6.3.0 20170516 (Debian 6.3.0-18) 
built with OpenSSL 1.1.0f  25 May 2017
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -fdebug-prefix-map=/data/builder/debuild/nginx-1.13.5/debian/debuild-base/nginx-1.13.5=. -specs=/usr/share/dpkg/no-pie-compile.specs -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-specs=/usr/share/dpkg/no-pie-link.specs -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'
root@dc7f2ee539a6:/# cat /etc/issue
Debian GNU/Linux 9 \n \l

可以看到,这个版本还是有点老了。同时看到,这个容器的操作系统 是Debian。

这时候使用IP地址直接访问:http://xxx..xxx:7777,可以看到熟悉的nginx欢迎页。同时启动容器的控制台会打印出访问日志。

[root@iZuf6jcwx7sfb1h6ayjq99Z docker-demo]# docker-compose up
Creating huanbao-nginx ... 
Creating huanbao-nginx ... done
Attaching to huanbao-nginx


huanbao-nginx | 27.38.175.141 - - [07/Jun/2018:17:22:22 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36" "-"
huanbao-nginx | 27.38.175.141 - - [07/Jun/2018:17:22:27 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36" "-"
huanbao-nginx | 27.38.175.141 - - [07/Jun/2018:17:22:27 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36" "-"

安装php-fpm

我们再加一个php-fpm进去。并要让nignx跟php-fpm通信,需要通过links指令。

version: "3.1"
services:
    nginx:
      image: nginx
      container_name: huanbao-nginx
      links:
       - php-fpm
      ports:
       - "7777:80"
    php-fpm:
      image: php:7.2-fpm
      container_name: huanbao-php-fpm

这时候再启动,就有huanbao-php-fpm和huanbao-nginx两个容器在运行了。但这样并没有什么实质作用,我们需要的是nginx传递请求给php来处理。首先,定一个网站目录,假定在在物理机中是当前目录(docker-compose.yml所在目录)下的huanbao目录为网站要根目录,容器内部定哪里呢,其实无所谓,姑且定为/huanbao(不必纠结内部nginx默认网站目录在哪里,其实是在/usr/share/nginx/html)。然后还得有一个nginx的网站配置。物理机定为当前目录下的nginx/conf/huanbao.conf,容器内部就得昨映射到内部nginx配置文件目录:/etc/nginx/conf.d/huanbao.conf。

nginx/conf/huanbao.conf必须先创建好再启动,否则使用volumes指令来映射时会被当作目录来处理。配置文件的内容如下:

version: "3.1"
services:
    nginx:
      image: nginx
      container_name: huanbao-nginx
      links:
       - php-fpm
      ports:
       - "7777:80"
      volumes:
       - ./huanbao:/huanbao
       - ./nginx/conf/huanbao.conf:/etc/nginx/conf.d/huanbao.conf
    php-fpm:
      image: php:7.2-fpm
      container_name: huanbao-php-fpm
server {
 
    listen 80;
 
    server_name xxx.xxx.xxx.xxx;
 
    root /huanbao;
 
    location / {
        index index.html index.htm index.php;
        try_files $uri $uri/ /index.php$is_args$args;
    }
 
    location ~ \.php$ {
        fastcgi_pass   php-fpm:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
 
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
}

很标准简洁的一个配置。需要注意的是fastcgi_pass这一项的值是:php-fpm:9000,是服务名+端口,不能写本机127.0.0.0或者localhost之类,也不是容器名huanbao-php-fpm,而是服务名php-fpm。再在网站目录建一个index.php输出一下phpinfo()。再启动后访问之。

[root@iZuf6jcwx7sfb1h6ayjq99Z docker-demo]# docker-compose up
Starting huanbao-php-fpm ... 
Starting huanbao-php-fpm ... done
Recreating huanbao-nginx ... 
Recreating huanbao-nginx ... done
Attaching to huanbao-php-fpm, huanbao-nginx
huanbao-php-fpm | [07-Jun-2018 18:07:00] NOTICE: fpm is running, pid 1
huanbao-php-fpm | [07-Jun-2018 18:07:00] NOTICE: ready to handle connections
huanbao-php-fpm | 192.168.80.3 -  07/Jun/2018:18:07:05 +0000 "GET /index.php" 404
huanbao-nginx | 2018/06/07 18:07:05 [error] 5#5: *1 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: 27.38.175.141, server: 106.14.33.138, request: "GET / HTTP/1.1", upstream: "fastcgi://192.168.80.2:9000", host: "106.14.33.138:7777"
huanbao-nginx | 27.38.175.141 - - [07/Jun/2018:18:07:05 +0000] "GET / HTTP/1.1" 404 27 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36"

不太妙。浏览器显示的是“File not found.”。这是因为nginx与php-fpm是分别运行在两个单独的容器内部的,nginx映射的网站根目录,php-fpm并不能访问得到,同样需要映射。

version: "3.1"
services:
    nginx:
      image: nginx
      container_name: huanbao-nginx
      links:
       - php-fpm
      ports:
       - "7777:80"
      volumes:
       - ./huanbao:/huanbao
       - ./nginx/conf/huanbao.conf:/etc/nginx/conf.d/huanbao.conf
    php-fpm:
      image: php:7.2-fpm
      container_name: huanbao-php-fpm
      volumes:
       - ./huanbao:/huanbao

重新访问,就能看到正常的phpinfo()输出了。

自定义php配置

很多情况下,我们需要修改php的一些默认配置,比如时区、比如最大上传文件大小。在容器内部,自定义的php.ini应该放到/usr/local/etc/php/conf.d目录下。新建一个my.ini,修改一下默认时区,只需要一行: date.timezone = PRC。

version: "3.1"
services:
    nginx:
      image: nginx
      container_name: huanbao-nginx
      links:
       - php-fpm
      ports:
       - "7777:80"
      volumes:
       - ./huanbao:/huanbao
       - ./nginx/conf/huanbao.conf:/etc/nginx/conf.d/huanbao.conf
    php-fpm:
      image: php:7.2-fpm
      container_name: huanbao-php-fpm
      volumes:
       - ./huanbao:/huanbao 
       - ./php-fpm/conf/my.ini:/usr/local/etc/php/conf.d/my.ini

添加php扩展

默认的php:7.2-fpm镜像只带了以下扩展。

[root@iZuf6jcwx7sfb1h6ayjq99Z docker-demo]# docker exec -it huanbao-php-fpm bash
root@1a1dfe663315:/var/www/html# php -m
[PHP Modules]
Core
ctype
curl
date
dom
fileinfo
filter
ftp
hash
iconv
json
libxml
mbstring
mysqlnd
openssl
pcre
PDO
pdo_sqlite
Phar
posix
readline
Reflection
session
SimpleXML
sodium
SPL
sqlite3
standard
tokenizer
xml
xmlreader
xmlwriter
zlib

[Zend Modules]

是的,没有看错,很坑爹的没有pdo_mysql。要安装其他扩展,就不能直接使用现有的镜像了,因此要把image指令换成build指令,基于现在有镜像重新生成一个。

version: "3.1"
services:
    nginx:
      image: nginx
      container_name: huanbao-nginx
      links:
       - php-fpm
      ports:
       - "7777:80"
      volumes:
       - ./huanbao:/huanbao
       - ./nginx/conf/huanbao.conf:/etc/nginx/conf.d/huanbao.conf
    php-fpm:
      container_name: huanbao-php-fpm
      build:
       context: ./php-fpm
      volumes:
       - ./huanbao:/huanbao 
       - ./php-fpm/conf/my.ini:/usr/local/etc/php/conf.d/my.ini

在build指令下,通过context指令指定工作上下文,也就是php-fpm的构建目录。在构建目录中,新建一个Dockerfile文件,内容很简单:基于php:7.2-fpm,安装 pdo_mysql扩展:


FROM php:7.2-fpm
RUN docker-php-ext-install pdo_mysql

安装mysql

PS:

要删除镜像与容器全新构建,docker system prune -a。可参考这里

当构建laravel应用时,若只有php使用docker,nginx仍然是宿主机时,不要在容器内部执行php artisan storage:link,这样子得出的storage路径是容器内部的,不是宿主机的,要手动在宿主机执行,如 ln -s /mnt/www/meiche/code/storage/app/public /mnt/www/meiche/code/public/storage。格式是 ln -s 源目录 目标目录。另,容器内部的php链接宿主机的mysql,host直接写宿主机的本地IP即可(ifconfig查看)。这时候mysql仍然当docker内部的php为外网连接,注意开放权限。

Leave a Reply

Your email address will not be published. Required fields are marked *

*

Time limit is exhausted. Please reload CAPTCHA.