环境安装参考前篇。前篇写得不是很详细,过后就忘,再来一次!
安装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 源目录 目标目录。如:
ln -s /mnt/www/meiche/code/storage/app/public /mnt/www/meiche/code/public/storage
对于不经过入口文件转发的资源文件,还得改写下根目录 root 才能被正常访问:
location ~* (vendor|storage|image|\.css|\.js|\.jpg|\.png|\.gif) { root /root/meiche/code/public; }
另,容器内部的php链接宿主机的mysql,host直接写宿主机的本地IP即可(ifconfig查看)。这时候mysql仍然当docker内部的php为外网连接,注意开放权限。
重启其中某个服务:docker-compose restart <服务名>,注意是服务不是容器名。