[关闭]
@dungan 2020-11-17T01:12:46.000000Z 字数 8015 阅读 107

Docker

Docker 实战


一、Lnmp

1. 集成式 Lnmp 环境

在 ubuntu 容器中借助 oneinstack 安装包生成 Lnmp 环境,然后将此 Ubuntu 容器打包成一个镜像:

  1. # 启动 ubuntu 容器
  2. $ docker run -itd --name ubuntu ubuntu:latest
  3. 1692725c0b57e5c9a0cc620bb95124d7ab1f8588dd4e8ee77c805dd2175cb679
  4. $ docker ps
  5. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  6. 1692725c0b57 ubuntu:latest "/bin/bash" 5 seconds ago Up 4 seconds ubuntu
  7. # 进入 ubuntu 容器
  8. $ docker exec -it ubuntu bash
  9. # 一键安装 Lnmp
  10. root@1692725c0b57:/# wget -c http://mirrors.linuxeye.com/oneinstack-full.tar.gz && tar xzf oneinstack-full.tar.gz && ./oneinstack/install.sh --nginx_option 1 --php_option 7 --phpcache_option 1 --php_extensions imagick,fileinfo,redis,memcached,memcache,mongodb,swoole,xdebug --phpmyadmin --db_option 2 --dbinstallmethod 1 --dbrootpwd oneinstack --pureftpd --redis --memcached --iptables --reboot
  11. # 安装 composer
  12. root@1692725c0b57:/# curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
  13. root@1692725c0b57:/# exit
  14. exit
  15. # 将ubuntu容器打包成一个镜像
  16. $ docker commit -m "lnmp images" -a "dunagan" 1692 dungan/lnmp
  17. sha256:46b19a77fef2cf601732009643f51a0aa8a251d9bfb47066d269fd5e291a39e4
  18. $ docker images
  19. REPOSITORY TAG IMAGE ID CREATED SIZE
  20. dungan/lnmp latest 46b19a77fef2 About a minute ago 4.08GB
  21. ...
  22. # 基于刚刚打包的 dungan/lnmp 镜像启动一个容器
  23. $ docker run -it dungan/lnmp:latest bash
  24. root@56fd2d4408d0:/# php -v
  25. PHP 7.2.32 (cli) (built: Jul 23 2020 17:45:14) ( NTS )
  26. Copyright (c) 1997-2018 The PHP Group
  27. Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
  28. with Zend OPcache v7.2.32, Copyright (c) 1999-2018, by Zend Technologies
  29. with Xdebug v2.9.5, Copyright (c) 2002-2020, by Derick Rethans
  30. root@56fd2d4408d0:/# nginx -v
  31. nginx version: nginx/1.18.0

这样构建的集成式Lnmp环境就运行起来了,但还有几个问题需要解决下。

1.1 Composer 的使用问题

使用 composer :

  1. // 第一种:
  2. docker run --rm -w /data/www/project composer:latest composer update
  3. // 第二种
  4. docker exec -it f9 /usr/local/bin/composer -V
  5. // docker exec -it f9 /bin/sh -c "/usr/local/bin/composer -V"

如果运行composer时出现如下错误 :

  1. $ docker exec -it f9 /bin/sh -c "/usr/local/bin/composer"
  2. /usr/bin/env: 'php': No such file or directory

这是由于 php 没有在 /usr/bin 下找,修复此问题只需要做个软链接就可以了 :

  1. // 为了避免 docker exec 时我们需要全路径引用相关的服务,对 nginx,composer也做下软连接
  2. ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx
  3. ln -s /usr/local/php/bin/php /usr/bin/php

1.2 PhpStorm 中连接 CLI Interpreter

默认情况下,docker 为了安全起见支支持 从 unixsock 连接,而不支持通过 TCP 连接,但 PhpStorm 又必须通过 TCP API 的方式连接 Docker 中的 php CLI interpreter,因此为了支持 Docker Daemon 通过Remote API 连接做如下配置:

  1. $ vim /etc/docker/daemon.json
  2. {
  3. "registry-mirrors":["https://hub-mirror.c.163.com/"],
  4. "debug": true,
  5. "hosts": ["tcp://localhost:2375","unix:///var/run/docker.sock"]
  6. }
  7. $ service docker restart

然后我们在 phpStorm 中就可以通过 TCP API 连接 Docker 了,关于这块的具体介绍见 这里

2020-08-01_182500.png

1.3 Push 镜像到 DockerHub

最后我们试着将生成的镜像 dungan/lnmp:latest Push 到 DockerHub。

  • 在 docker-hub 新建镜像仓库:例如叫做 lnmp,这类似 github,每个项目都有自己的仓库。
  • 修改镜像名称:格式为为 <username>/<reponame>:<tagname> ,例如 dungan/lnmp:v1.0
  • 登录 DockerHub: docker login
  • push 镜像:docker push dungan/lnmp:latest
  1. $ docker push dungan/lnmp:latest
  2. The push refers to repository [docker.io/dungan/lnmp]
  3. 349ed4d1fa0d: Pushing [===> ] 276MB/4.004GB
  4. 544a70a875fc: Pushed
  5. cf0f3facc4a3: Pushed
  6. 132bcd1e0eb5: Pushed
  7. d22cfd6a8b16: Pushed

很不幸会失败的,因为我们构建出来的这个镜像 dungan/lnmp 大小竟然为 4.08G。

可以看到这种集成式的 Lnmp 环境问题多多,我们只能另辟蹊径,看看将各个组件独立成单一的容器能带给我们那些不一样的收获。

2. 独立的 Nginx、Mysql、PHP

2.1 容器间通信

独立的容器组件首先遇到的是互相通信的问题,对此 docker 提供了两种解决方案:自定义网络容器互联

2.1.1 自定义网络

容器默认加入的网络 bridge 便是 docker0,我们可以通过docker network inspect 命令来查看一下这个 bridge 网络:

  1. $ docker network inspect bridge
  2. [
  3. {
  4. "Name": "bridge",
  5. "Id": "499548da01b39013949d6e22f2b1afa6db2153246850ebd9e860ca1860094316",
  6. "Created": "2020-07-24T18:01:04.9259454+08:00",
  7. "Scope": "local",
  8. "Driver": "bridge",
  9. "EnableIPv6": false,
  10. "IPAM": {
  11. "Driver": "default",
  12. "Options": null,
  13. "Config": [
  14. {
  15. "Subnet": "172.17.0.0/16",
  16. "Gateway": "172.17.0.1"
  17. }
  18. ]
  19. },
  20. "Internal": false,
  21. "Attachable": false,
  22. "Ingress": false,
  23. "ConfigFrom": {
  24. "Network": ""
  25. },
  26. "ConfigOnly": false,
  27. "Containers": {
  28. "1692725c0b57e5c9a0cc620bb95124d7ab1f8588dd4e8ee77c805dd2175cb679": {
  29. "Name": "ubuntu",
  30. "EndpointID": "e88b34e46377429d5598b0e7dd01d27f321c3d10b6541b72db599193ac433ddb",
  31. "MacAddress": "02:42:ac:11:00:03",
  32. "IPv4Address": "172.17.0.3/16",
  33. "IPv6Address": ""
  34. },
  35. "56fd2d4408d091df243f468a6558891d683f58a6437e47a71510f184b7abd7d0": {
  36. "Name": "lnmp",
  37. "EndpointID": "dec4ea0917479775fa91bd373c0f437882b01145bbfca8e28592a2eaaa79e648",
  38. "MacAddress": "02:42:ac:11:00:02",
  39. "IPv4Address": "172.17.0.2/16",
  40. "IPv6Address": ""
  41. }
  42. }
  43. ...
  44. }
  45. ]

Docker 支持用户手动创建网络,以及手动将容器加入某个网络:

  1. docker network create lnmp
  2. docker network connect lnmp mysql
  3. docker network connect lnmp nginx

通过 docker inspect CONTAINER 命令来查看容器信息,可以看到两个容器分别获得了 172.18.0.2 和 172.18.0.3 的IP,他们之间可以通过这一子网进行通信了。

可以看到通过加入相同子网(默认的bridge或者自定义子网)的容器可以实现互相通信。

2.1.2 容器互联

--link 容器互联的原理:

--link 实现容器互联的原理是通过修改容器内的 hosts 文件,比如容器A --link 容器B,这时 Docker 就会修改容器 A 的 hosts 文件,将容器 B 及对应的 IP 添加进去。但使用 --link 会造成容器之间的绑定,前面的例子中,若删除容器B,容器A将无法运行,即使重新创建一个相同名称的容器B,容器A仍然无法运行,这显然是我们不想看到的。

不过需要注意:

Docker 官方文档已经明确提出 --link将在未来版本中移除,鼓励使用自定义网络来实现用户间的通信,并指出例如共享环境变量这样可以通过--link实现而无法通过自定义网络实现的功能则推荐使用volumes的方式解决。

2.1.3 总结

2.2 复制配置文件

将配置文件复制出来,方便后续重新启动容器时进行数据卷映射。

Nginx:

  1. $ docker run --name nginx -d nginx
  2. $ docker cp nginx:/etc/nginx /mnt/d/docker/nginx
  3. $ docker cp nginx:/usr/share/nginx/html /mnt/d/docker/www
  4. $ docker stop nginx
  5. $ docker rm nginx
  6. $ ll /mnt/d/docker/
  7. drwxrwxrwx 1 tcl tcl 4096 Jul 22 11:23 nginx/
  8. drwxrwxrwx 1 tcl tcl 4096 Jul 22 11:23 www/

MySQL:

  1. $ docker run --name mysql -e MYSQL_ROOT_PASSWORD=root -d -p 3306:3306 mysql:5.7
  2. $ docker cp mysql:/etc/mysql /mnt/d/docker/mysql
  3. $ docker stop mysql
  4. $ docker rm mysql
  5. $ ll /mnt/d/docker/
  6. drwxrwxrwx 1 tcl tcl 4096 Jul 23 04:15 mysql/
  7. drwxrwxrwx 1 tcl tcl 4096 Jul 22 11:23 nginx/
  8. drwxrwxrwx 1 tcl tcl 4096 Jul 22 11:23 www/

PHP-FPM:

  1. $ docker run --name phpfpm -d -P php:7.2-fpm
  2. $ docker cp phpfpm:/usr/local/etc/php /mnt/d/docker/php
  3. $ docker stop phpfpm
  4. $ docker rm phpfpm
  5. $ ll /mnt/d/docker/
  6. drwxrwxrwx 1 tcl tcl 4096 Jul 23 04:15 mysql/
  7. drwxrwxrwx 1 tcl tcl 4096 Jul 22 11:23 nginx/
  8. drwxrwxrwx 1 tcl tcl 4096 Jul 22 19:14 phpfpm/
  9. drwxrwxrwx 1 tcl tcl 4096 Jul 22 11:23 www/

2.3 重新运行各个容器

重新运行各个容器以作数据卷映射。

Nginx:

  1. docker run -d -it --name nginx \
  2. -v /mnt/d/docker/nginx:/etc/nginx \
  3. -v /mnt/d/docker/www:/usr/share/nginx/html \
  4. -p 80:80 \
  5. -p 443:443 \
  6. nginx \
  7. /bin/bash

MySql:

  1. docker run -d -it --name mysql \
  2. -e MYSQL_ROOT_PASSWORD=root \
  3. -v /mnt/d/docker/mysql:/etc/mysql \
  4. -p 3306:3306 \
  5. mysql:5.7 \
  6. /bin/bash

PHP:

由于 docker 官方的 php-fpm 为了减少体积并未包含大部分扩展,因此为了安装没有的扩展,我们构造 Dockerfile 如下:

  1. FROM php:7.2-fpm
  2. RUN mv /etc/apt/sources.list /etc/apt/sources.list.bak \
  3. && echo 'deb http://mirrors.aliyun.com/debian/ buster main non-free contrib' > /etc/apt/sources.list \
  4. && echo 'deb http://mirrors.aliyun.com/debian-security buster/updates main' >> /etc/apt/sources.list \
  5. && echo 'deb http://mirrors.aliyun.com/debian/ buster-updates main non-free contrib' >> /etc/apt/sources.list \
  6. && echo 'deb http://mirrors.aliyun.com/debian/ buster-backports main non-free contrib' >> /etc/apt/sources.list \
  7. && apt-get update \
  8. && apt-get install -y --no-install-recommends \
  9. libfreetype6-dev \
  10. libjpeg62-turbo-dev \
  11. libpng-dev \
  12. libmagickwand-dev \
  13. libmcrypt-dev \
  14. && rm -rf /var/lib/apt/lists/* \
  15. && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
  16. && docker-php-ext-install -j$(nproc) gd \
  17. && docker-php-ext-install mysqli \
  18. && pecl install imagick-3.4.4 && pecl install mcrypt-1.0.2 && pecl install redis-5.1.1 \
  19. && pecl install xdebug-2.7.2 && pecl install swoole-4.4.3 \
  20. && docker-php-ext-enable imagick mcrypt redis xdebug swoole \
  21. && curl -sS https://getcomposer.org/installer |php -- --install-dir=/usr/local/bin --filename=composer
  22. && docker-php-source delete \
  23. && rm -r /tmp/* /var/cache/* /var/www/html/*

注意:上述 Dockerfile 中我们一并打包了 composer,更多关于php扩展的安装见 这里docker官方

接下来,基于 Dockefile 构造我们自己的 phpfmp 镜像:

  1. $ docker build -t dungan/phpfpm7.2 .
  2. $ docker images
  3. REPOSITORY TAG IMAGE ID CREATED SIZE
  4. dungan/phpfpm7.2 latest 1c0ef877da7e 2 hours ago 631MB

最后基于此镜像启动一个容器:

  1. docker run --name phpfpm -d -P \
  2. -v /mnt/d/docker/www:/usr/share/nginx/html \
  3. -v /mnt/d/docker/php:/usr/local/etc/php \
  4. dungan/phpfpm7.2:latest

注意:站点下的 php 脚本如果想在 CLI 模式下执行,就必须将 www 映射到 phpfpm 容器中去。

2.4 配置容器通信

创建自定义网络,将各容器加入该自定义网络。

  1. $ docker network create lnmp
  2. 2c934afb36b871ea49f911c87e7beb3cd6279e18853f2c31d625e718db64f68c
  3. $ docker network connect lnmp nginx
  4. $ docker network connect lnmp mysql
  5. $ docker network connect lnmp phpfpm

修改nginx配置文件:

  1. server{
  2. ...
  3. location ~ \.php$ {
  4. root /usr/share/nginx/html;
  5. fastcgi_pass phpfpm:9000;
  6. fastcgi_index index.php;
  7. fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  8. include fastcgi_params;
  9. }
  10. ...
  11. }

然后重启 Nginx :

  1. $ docker restart nginx

二、Go

三、Redis

四、MongoDB

五、ES

六、队列

1. Rabbitmq

2. Kakfa

七、参考

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注