PHP Swoole Swoft

参考资料

Swoft是在Swoole之上构建的一个高性能协程PHP全栈框架,内置协程网络服务器及常用协程客户端,常驻内存,不依赖PHP-FPM,全异步非阻塞IO实现,以类似同步客户端的写法实现异步客户端的使用,没有负责的异步回调和繁琐的yield,有类似Go语言的协程、灵活的注解、强大的全局依赖注入容器、完善的服务治理、灵活强大的AOP、标准的PSR规范实现等,可用来构建高性能的Web系统、API、中间件、基础服务等功能。

环境需求

  • PHP版本必须大于7.1
 swoft/component 2.0 requires php >7.1.0
  • 必须安装PHP包管理工具composer
  • 必须安装Redis的异步客户端hiredis
  • 必须安装PHP扩展swoole,Swoole版本至少大于2.1
  • Swoole必须开启协程和异步Redis
  • PHP必须启动PDO扩展

冲突解决

与Swoole有冲突的PHP扩展:xdebugxhprofblackfirezendtraceuopz,需要禁用或不安装。

环境搭建

手工安装Swoft

$ git clone https://github.com/swoft-cloud/swoft
$ cd swoft

# 使用composer中国镜像
$ composer config -g repo.packagist composer https://packagist.laravel-china.org

# 不安装dev依赖,加快速度。
$ composer install --no-dev
Cloning failed using an ssh key for authentication, enter your GitHub credentials to access private repos

$ composer config --global --auth github-oauth.github.com <token>

# 设置环境配置文件
$ cp .env.example .env
$ vim .env

Docker安装Swoft

Docker

Docker是一个开源的应用容器引擎,让开发者可以打包应用及依赖到一个可移植的容器中,然后发布到任何流行的Linux机器上。Docker可以实现虚拟化,而且是完全使用沙箱机制,相互之间不会有任何接口。简单来说,可以理解为将代码和运行环境打包到一个容器,然后发布到机器上。

Windows10安装Docker

由于本地测试使用,使用Windows10安装Docker,建议使用Linux安装Docker。

Docker For Windows

Docker For Windows 是新一代的平台. 官方也更支持. 支持Windows container 但是存在一个缺点,必须使用 HyperV 的虚拟化平台。但是开启了HyperV 的角色之后Windows10 更像是运行在HyperV 上面的一个虚拟机了, 也就意味着着 Workstation还有Virtualbox 这样的虚拟化平台就无法使用了。

Docker的Windows10安装包:https://hub.docker.com/editions/community/docker-ce-desktop-windows

Windows10版本需求:Docker Desktop requires Windows 10 Pro or Enterprise version 14393 to run

Docker可以支持在 Mac、Windows、Linux 上安装,但是在 Windows10 系统中Docker for Windows目前只能在 64 位的 Windows10 专业版、企业版、教育版下才能安装,Win7/Win8/Win10 家庭版需要通过Docker Toolbox来安装。家庭版不支持Hyper-V,Docker Desktop是无法直接安装的。

Windows家庭版

家庭版通过脚本开启Hyper-V

创建hyper-v.bat批处理文件,以管理员身份运行。

$ vim hyper-v.bat
pushd "%~dp0"

dir /b %SystemRoot%\servicing\Packages\*Hyper-V*.mum >hyper-v.txt

for /f %%i in ('findstr /i . hyper-v.txt 2^>nul') do dism /online /norestart /add-package:"%SystemRoot%\servicing\Packages\%%i"

del hyper-v.txt

Dism /online /enable-feature /featurename:Microsoft-Hyper-V-All /LimitAccess /ALL

确认Windows10是否已经开启Hyper-V

控制面板 -> 程序 -> 启用或关闭Windows功能 -> 选中Hyper-V

Hyper-V

伪装成专业版绕过安装检测

Ctrl+R运行中输入regedit打开注册表,定位到HKEY_LOCAL_MACHINE\software\Microsoft\Windows NT\CurrentVersion中选中EditionId,右键修改,将“数值数据”修改为Professional,确认关闭。

regedit

可使用管理员权限运行CMD命令实现同样操作

REG ADD "HKEY_LOCAL_MACHINE\software\Microsoft\Windows NT\CurrentVersion" /v EditionId /T REG_EXPAND_SZ /d Professional /F

安装成功后启动后出现 Docker doesn't support your Windows version. Check documentation for minimum requirements

Docker不支持Windows家庭版

查看是否Windows10是否开启了虚拟化

Windows10开启虚拟化

启动BIOS的虚拟化设置,开启CPU虚拟化支持

进入到BIOS后,找到Configuration选项或者Security选项,然后选择Virtualization,或者Intel Virtual Technology,

此路不通,选择Docker Toolbox。

Docker Toolbox

Docker Toolbox 自带一个VirtualBox的驱动, 能够生成一个VirtualBox的虚拟机,作为Docker deamon的运行使用,一般设置2G 内存 进行运行。它的优点是自带VB兼容性好,Windows 下面基本上都可以运行。缺点是不支持Windows的container 只能运行Linux container。

通过docker toolbox来安装docker

Docker Toolbox

Docker的Toolbox有CE和EE版,CE为免费版,EE由公司支持的付费版。Docker for Windows是依赖 Hyper-v 的,但是Docker Toolbox是用VirtualBox的

Docker Toolbox工具集主要包括:

  • Docker CLI 客户端,用来运行docker引擎创建镜像和容器
  • Docker Machine. 可以让你在windows的命令行中运行docker引擎命令
  • Docker Compose. 用来运行docker-compose命令
  • Kitematic. 这是Docker的GUI版本
  • Docker QuickStart shell. 这是一个已经配置好Docker的命令行环境
  • Oracle VM Virtualbox. 虚拟机

由于Docker引擎的守护进程使用Linux的内核,所以不能直接在Windows中运行Docker引擎。需要运行Docker Machine命令docker-machine,在机器上创建或获取一个Linux虚拟机,用这个Linux虚拟机才可以在Windows系统上运行Docker引擎。

下载安装这些流程就不说了,安装时的选项需要注意下选项。

Docker Toolbox

Docker Quickstart Terminal 启动报错

Running pre-create checks...
Error with pre-create check: "This computer is running Hyper-V. VirtualBox won't boot a 64bits VM when Hyper-V is activated. Either use Hyper-V as a driver, or disable the Hyper-V hypervisor. (To skip this check, use --virtualbox-no-vtx-check)"
Looks like something went wrong in step ´Checking if machine default exists´... Press any key to continue...

Windows 8.1 Hyper-V 与 VirtualBox, VMware 有冲突,即 Windows 8.1 Hyper-V 安装后, VirtualBox 以及 VMware 无法创建或执行 64bit 虚拟机。

直接把Hyepr-v禁用,管理员模式运行 CMD

# 禁用Hyepr-v
$ bcdedit /set hypervisorlaunchtype off

# 启用Hyepr-v
$ bcdedit /set hypervisorlaunchtype auto 

修改启动文件以允许它创建默认的 VM

以管理员身份打开C:\Program Files\Docker Toolbox\start.sh并修改

  # "${DOCKER_MACHINE}" create -d virtualbox $PROXY_ENV "${VM}"
  "${DOCKER_MACHINE}" create -d virtualbox --virtualbox-no-vtx-check $PROXY_ENV "${VM}"

使用管理员打开cmd命令行

$ bcdedit /copy {current} /d "No Hyper-V"
已将该项成功复制到 {14cfe56b-60bb-11e9-82c8-0c96e6d1d776}
$ bcdedit /set {14cfe56b-60bb-11e9-82c8-0c96e6d1d776} hypervisorlaunchtype off
操作成功完成

Docker Quickstart Terminal 启动报错

Starting "default"...
(default) Check network to re-create if needed...
(default) Windows might ask for the permission to configure a dhcp server. Sometimes, such confirmation window is minimized in the taskbar.
Unable to start the VM: C:\Program Files\Oracle\VirtualBox\VBoxManage.exe startvm default --type headless failed:
VBoxManage.exe: error: Raw-mode is unavailable courtesy of Hyper-V. (VERR_SUPDRV_NO_RAW_MODE_HYPER_V_ROOT)
VBoxManage.exe: error: Details: code E_FAIL (0x80004005), component ConsoleWrap, interface IConsole

Details: 00:00:01.647988 Power up failed (vrc=VERR_SUPDRV_NO_RAW_MODE_HYPER_V_ROOT, rc=E_FAIL (0X80004005))
Looks like something went wrong in step ´Checking status on default´... Press any key to continue...

这个错误怎么办?简单粗暴的方法,直接杀死VirtualBox进程,然后重启Docker Quickstart Terminal。

关掉Hyper-V之后,重启电脑。

打开Docker Quickstart Terminal,开启之后会自动加载一个Linux 虚拟机。使用管理员身份打开VirtualBox,可以看到有一个default的虚拟机正在运行。

VirtualBox default

进入default虚拟机查看IP地址

$ ifconfig | grep eth
$ ifconfig eth1
inet addr:192.168.99.100

虚拟机操作命令

# 初始化 Virtual Box 的 default 虚拟机
$ docker-machine create –driver virtualbox default

# 查看虚拟机环境
$ docker-machine env
SET DOCKER_TLS_VERIFY=1
SET DOCKER_HOST=tcp://192.168.99.100:2376
SET DOCKER_CERT_PATH=C:\Users\junchow\.docker\machine\machines\default
SET DOCKER_MACHINE_NAME=default
SET COMPOSE_CONVERT_WINDOWS_PATHS=true
REM Run this command to configure your shell:
REM     @FOR /f "tokens=*" %i IN ('docker-machine env') DO @%i

# 查看虚拟机状态,注意如果在VirtualBox中打开虚拟机后,命令行中将会显示为stop状态。
$ docker-machine status

# 开启虚拟机
$ docker-machine start
Starting "default"...
(default) Check network to re-create if needed...
(default) Windows might ask for the permission to configure a dhcp server. Sometimes, such confirmation window is minimized in the taskbar.
Error setting up host only network on machine start: C:\Program Files\Oracle\VirtualBox\VBoxManage.exe modifyvm default --nic2 hostonly --nictype2 82540EM --nicpromisc2 deny --hostonlyadapter2 VirtualBox Host-Only Ethernet Adapter #2 --cableconnected2 on failed:
VBoxManage.exe: error: Code E_FAIL (0x80004005) - Unspecified error (extended info not available)
VBoxManage.exe: error: Context: "LockMachine(a->session, LockType_Write)" at line 525 of file VBoxManageModifyVM.cpp

# 关闭虚拟机
$ docker-machine stop

# 重启虚拟机
$ docker-machine restart

# 使用SSH连接虚拟机
$ docker-machine ssh default

一路折腾重启后终于出现了

                        ##         .
                  ## ## ##        ==
               ## ## ## ## ##    ===
           /"""""""""""""""""\___/ ===
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ /  ===- ~~~
           \______ o           __/
             \    \         __/
              \____\_______/

docker is configured to use the default machine with IP 192.168.99.100
For help getting started, check out the docs at https://docs.docker.com


Start interactive shell

junchow@DESKTOP-H6DQQNO MINGW64 /c/Program Files/Docker Toolbox
Docker Quickstart Terminal

执行docker命令测试下

$ docker -v
Docker version 18.03.0-ce, build 0520e24302

$ docker version
Client:
 Version:       18.03.0-ce
 API version:   1.37
 Go version:    go1.9.4
 Git commit:    0520e24302
 Built: Fri Mar 23 08:31:36 2018
 OS/Arch:       windows/amd64
 Experimental:  false
 Orchestrator:  swarm

Server: Docker Engine - Community
 Engine:
  Version:      18.09.5
  API version:  1.39 (minimum version 1.12)
  Go version:   go1.10.8
  Git commit:   e8ff056dbc
  Built:        Thu Apr 11 04:50:00 2019
  OS/Arch:      linux/amd64
  Experimental: false

$ docker-compose -v
docker-compose version 1.20.1, build 5d8c71b2

# 显示所有镜像
$ docker images

Kitematic (Alpha)

Kitematic 是一个UI的container 管理界面,能够 从docker hub 中拉取images 执行, 并且查看web页面 修改配置, 修改volume 等工作。打开Kitematic,登录到DockerHub可获取公共镜像。

Kitematic

使用Docker Quickstart Terminal命令行非常不方便,还是使用Cmder进行Docker的处理比较方便。

Cmder
$ @FOR /f "tokens=*" %i IN ('docker-machine env default') DO @%i

容器操作命令

# 查看启动的容器信息
$ docker ps

# 查看所有容器
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS                      PORTS                  NAMES
14ac8225efd9        nginx               "nginx -g 'daemon of…"   4 hours ago          Created                                            priceless_elbakyan
b2c0db6bc301        nginx               "nginx -g 'daemon of…"   4 hours ago          Created                                            vigilant_varahamihira
fd1384877d56        nginx               "nginx -g 'daemon of…"   4 hours ago          Created                                            amazing_dijkstra
af8d7a9a6023        nginx               "nginx -g 'daemon of…"   4 hours ago          Created                                            goofy_galileo
02a7f4f5f1ce        nginx               "nginx -g 'daemon of…"   4 hours ago          Exited (0) 10 minutes ago                          serene_bohr                                                                                                                                          

# 运行一个容器
$ docker run -d -p 8888:80 nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
27833a3ba0a5: Pull complete
ea005e36e544: Pull complete
d172c7f0578d: Pull complete
Digest: sha256:ad250db8c3c15a6d4ee51a9e6947ca16a1010bf958c9db1d7223450ac88e1f28

# 查看启动的容器信息
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
02a7f4f5f1ce        nginx               "nginx -g 'daemon of…"   3 minutes ago       Up 3 minutes        0.0.0.0:8888->80/tcp   serene_bohr

# 进入容器
# 使用该命令有一个问题:当多个窗口同时使用该命令进入该容器时,所有的窗口都会同步显示。
# 如果有一个窗口阻塞了,那么其他窗口也无法再进行操作。
# 所以docker attach命令不太适合于生产环境,平时自己开发应用时可以使用该命令。
$ docker attach 02a7f4f5f1ce

# 通过交互式终端(terminal)进入到容器内
$ docker exec -it 02a7f4f5f1ce bash
$ docker exec -it swoft bash

# 中止运行状态的容器
$ docker stop 02a7f4f5f1ce
02a7f4f5f1ce

# 停止所有容器才能删除其中的镜像
$ docker ps -a -q
1695c7d93229
$ docker stop $(docker ps -a -q)
unknown shorthand flag: 'a' in -a
See 'docker stop --help'.

# 删除所有容器
$ docker rm $(docker ps -a -q)

# 将一个已经处于中止状态的容器删除
$ docker rm 02a7f4f5f1ce
02a7f4f5f1ce

镜像操作命令

# 查看当前容器中所有镜像
$ docker images

# 查看镜像信息
$ docker images nginx
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               latest              27a188018e18        10 hours ago        109MB

Docker无法删除镜像,由于是依赖容器。

Error response from daemon: conflict: unable to delete 493b8cc21299 (must be forced) - image is being used by stopped container 1695c7d93229

解决的方式是先删除容器,在删除镜像。

$ docker ps 
$ docker rm container_id
$ docker images
$ docker rmi image_id
Kitematic

使用浏览器访问default虚拟机中的nginx:http://192.168.99.100:8888/

Kitematic

安装Swoft

不管采用那种方式安装Swoft,首先设置default虚拟机的共享目录并重启虚拟机,让虚拟机中的文件与本地机器对应起来。这样才能在本地修改代码后,docker中才能同步。

VirtualBox6.0.6设置共享目录

Docker安装Swoft镜像

Swoft官方提供了基于Debian的Docker镜像,镜像中已经安装配置好运行Swoft所需组件以及依赖。使用镜像可以开箱即用,免去繁琐的安装配置。

# 默认没有指定安装目录的位置,将会被安装到/var/www/目录下。
$ docker run -p 80:80 swoft/swoft
                         Server Information
********************************************************************
* HTTP | host: 0.0.0.0, port: 80, type: 1, worker: 1, mode: 3
* TCP  | host: 0.0.0.0, port: 8099, type: 1, worker: 1 (Enabled)
********************************************************************
Server has been started. (master PID: 1, manager PID: 6)
You can use CTRL + C to stop run.

docker run命令简要说明,详细内容可查看《Docker命令》

# docker run -d -p [宿主机端口]:[容器端口] -it -v [宿主机地址]:[容器地址] 容器名称 /bin/bash
-d, --detach=false 表示指定容器运行于前台还是后台,默认false表示后台。
-p, --publish-all=false 指定容器暴露的端口
-i, --interactive=false 表示打开STDIN标准输入用于控制台交互
-v, --volume=[] 给容器挂载存储卷,也就是挂载到容器的某个目录。
-t, --tty=false 分配tty设备用来支持终端登录,默认为false。

值得注意的是docker run -p 80:80 swoft/swoft启动容器时将swoft服务作为容器的进程,如果swoft进程退出容器就会关闭,容器启动时会根据Dockfile文件去执行php /var/www/swoft/bin/swoft start命令。

现在,查看下docker所有容器发现,有一个名为practical_chaum编号为2c34c8c76813得容器正Up 3 minutes。老铁,没错,这个容器现在运行正常。

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
2c34c8c76813        swoft/swoft         "php /var/www/swoft/…"   3 minutes ago       Up 3 minutes        0.0.0.0:80->80/tcp   practical_chaum

容器的名字叫做practical_chaum,不太容易能记住,来修改下:

docker@default:~$ docker rename practical_chaum swoft
docker@default:~$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
2c34c8c76813        swoft/swoft         "php /var/www/swoft/…"   32 minutes ago      Up 32 minutes       0.0.0.0:80->80/tcp   swoft

另外,如果查看docker的镜像会发现:

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
swoft/swoft         latest              493b8cc21299        2 months ago        447MB

进入swoft容器项目中,使用composer install加载composer.json的依赖并生成自动加载文件/vendor/autoload.php

$ docker exec -i -t practical_chaum bash
root@2c34c8c76813:/var/www/swoft# composer install
# 如果项目服务没有启动可以使用,我们现在已经是正在运行的状态中。
root@2c34c8c76813:/var/www/swoft# php bin/swoft start
The server have been running!(PID: 1)

看看swoft项目代码

root@2c34c8c76813:/var/www/swoft# ls
CONTRIBUTING.md  LICENSE    README_CN.md  bin           composer.json  config             docker-compose.yml  phpunit.xml  resources  test
Dockerfile       README.md  app           changelog.md  composer.lock  dev.composer.json  phar.build.inc      public       runtime    vendor

浏览器访问:http://192.168.99.100/

Swoft

swoft是运行起来,那我自己要写代码怎么操作? 怎么搞?怎么搞?能不能把当前容器的swoft项目同步到我的物理机上面,我每次修改后在同步到容器里面去呢?我猜想应该是可以的,不过...

首先第一点需要明确的是在创建容器时不能直接使用docker run -p 80:80 swoft/swoft,而需要使用:

$ docker run -d -i -t -p 81:81 -v /share/swoft:/var/www/swoft --privileged --entrypoint="" --name swoft1 swoft/swoft /bin/bash

为什么呢?其中涉及到两个非常重要的参数选项:

  • -v /share/swoft:/var/www/swoft 共享目录
  • --entrypoint=""启动点

可以观察两种不同方式的差异

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                          PORTS                        NAMES
2c546044f222        swoft/swoft         "/bin/bash"              6 seconds ago       Up 5 seconds                    80/tcp, 0.0.0.0:81->81/tcp   swoft1
2c34c8c76813        swoft/swoft         "php /var/www/swoft/…"   About an hour ago   Exited (0) About a minute ago                                swoft

重点看COMMAND,在swoft容器中使php /var/www/swoft/…,而在swoft1容器中是/bin/bash。好吧,只要去理解--entrypoint选项的含义这个问题就很好解答了。

本地安装Swoft

本地Composer配置

$ composer -v
Composer version 1.8.5 2019-04-09 17:46:47
$ composer self-update
$ composer dump-autoload
$ composer clear-cache

切换镜像为中国源 https://packagist.phpcomposer.com,不过我打开直接就是403,看来不用了。

$ composer config -g repo.packagist composer https://packagist.phpcomposer.com

切换到中国源,安装或更新的时候报404错 The "https://packagist.phpcomposer.com/p/provider-2019-04%248b0d8928e17b685afa0499b2b6241008aec0bcb7a26a9d0307e7d8642af87d12.json" file could not be downloaded (HTTP/1.1 404 Not Found)

$ composer install
Loading composer repositories with package information
Updating dependencies (including require-dev)
  [Composer\Downloader\TransportException]
  The "https://packagist.phpcomposer.com/p/provider-2019-04%248b0d8928e17b685afa0499b2b6241008aec0bcb7a26a9d0307e7d8642af87d12.json" file could not be downloaded (HTTP/1.1 404 Not Found)

算了,还是切换到 https://packagist.org,我这里是能打开的。

$ composer config -g repo.packagist composer https://packagist.org

本地PHP环境配置

$ php -v
PHP 7.2.1 (cli) (built: Jan  4 2018 04:28:54) ( NTS MSVC15 (Visual C++ 2017) x86 )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2017 Zend Technologies

预备使用share作为VirtualBox的共享目录

设置共享目录
$ cd d:\docker\share

下载安装swoft

$ git clone https://github.com/swoft-cloud/swoft
$ cd swoft
$ cp .env.example .env
$ composer install
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - This package requires php >=7.1 but your HHVM version does not satisfy that requirement.
  Problem 2
    - swoft/component 2.0 requires php >7.1.0 -> your PHP version (7.0.12) does not satisfy that requirement.
    - swoft/component 2.0 requires php >7.1.0 -> your PHP version (7.0.12) does not satisfy that requirement.
    - swoft/component 2.0 requires php >7.1.0 -> your PHP version (7.0.12) does not satisfy that requirement.
    - Installation request for swoft/annotation ^2.0 -> satisfiable by swoft/component[2.0].

淡淡地忧伤:your PHP version (7.0.12) does not satisfy that requirement,为什么呢?注意检查下PHP配置文件php.ini中是否打开了openssl扩展。全是坑,composer报的错让人误导。

使用Docker Machine查看下本地虚拟机,也就是宿主机,又称为主机的,不知道这样表达对不?

$ docker-machine ls
NAME      ACTIVE   DRIVER       STATE     URL   SWARM   DOCKER    ERRORS
default   -        virtualbox   Stopped                 Unknown

其中名为default的虚拟机处于关闭状态,使用docker-machine start default开启虚拟机。

$ docker-machine start default
Starting "default"...
(default) Check network to re-create if needed...
(default) Windows might ask for the permission to configure a dhcp server. Sometimes, such confirmation window is minimized in the taskbar.
(default) Waiting for an IP...
Machine "default" was started.
Waiting for SSH to be available...
Detecting the provisioner...
Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.

关于Docker Machine命令的使用,可参见《Docker Machine》

开启default虚拟机后,查看下它的状态,确认处于运行Running的状态。

$ docker-machine status default
Running 

接下来,使用Docker Machine提供的SSH命令连接到default虚拟机中去。

$ docker-machine ssh default
   ( '>')   ( '>')
  /) TC (\   Core is distributed with ABSOLUTELY NO WARRANTY.
 (/-_--_-\)           www.tinycorelinux.net

查看default虚拟机上存在的容器

docker@default:~$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                           PORTS                NAMES
6a1c6b9b067a        swoft/swoft         "/bin/bash"         3 hours ago         Exited (255) About an hour ago   0.0.0.0:80->80/tcp   swoft

可以看到名为swoft的容器正处于Exited (255) About an hour ago状态,由于处于Exited状态可以先移除它。

docker@default:~$ docker rm swoft
swoft

由于使用VirtualBox将default虚拟机与本地Windows物理机做共享目录,因此在default虚拟机的share目录下已经同步了Windows中swoft目录。这里,使用-v参数将default虚拟机的/share/swoft目录与swoft容器的/var/www/swoft目录设置为数据共享。

docker@default:~$ docker run -d -i -t -p 80:80 -v /share/swoft:/var/www/swoft --name swoft swoft/swoft /bin/bash
0aeec5f5e6f8f7fb3864843dd08be7c22a421a76d349d89a6e2040deb1b638b1

docker run命令需要重点学习下,加了个-rm选项表示如果启动失败则删除镜像,不过这样就看不到错误日志了。

docker@default:~$ docker run -d -i -t --rm -p 80:80 -v /share/swoft:/var/www/swoft --name swoft swoft/swoft /bin/bash

现在查看所有容器,发现swoft容器的状态仍然是Exited的,说明出现错误了。

docker@default:~$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                       PORTS               NAMES
0aeec5f5e6f8        swoft/swoft         "php /var/www/swoft/…"   3 seconds ago       Exited (255) 3 seconds ago                       swoft

出错了怎么办?当然是看日志找线索。打开docker logs swoft显示swoft容器的日志,可以看到错误就趴在那里,一动不动。

docker@default:~$ docker logs swoft

Fatal error: Uncaught Error: Class 'Swoole\Runtime' not found in /var/www/swoft/bin/swoft:7
Stack trace:
#0 {main}
  thrown in /var/www/swoft/bin/swoft on line 7

上面的错误说在swoft容器/var/www/swoft/bin/swoft文件的第7行出现了一个致命的错误Swoole\Runtime类不存在,的确这是一个致命的错误,文件丢失了吗,扩展没安装吗,猜测下。忽然想到一点,应该在Windows里面调试好Swoft后在做这些操作,错误不就可以避免了吗?是的,应该从源头上去控制。好吧,还是杀回去吧。

回到Windows下的swoft运行下,果然不错,差之毫厘谬之千里。哎...

$ d:
$ cd docker\share\swoft
$ php bin\swoft -h
PHP Fatal error:  Uncaught Error: Class 'Swoole\Runtime' not found in D:\docker\share\swoft\bin\swoft:7
Stack trace:
#0 {main}
  thrown in D:\docker\share\swoft\bin\swoft on line 7

Fatal error: Uncaught Error: Class 'Swoole\Runtime' not found in D:\docker\share\swoft\bin\swoft:7
Stack trace:
#0 {main}
  thrown in D:\docker\share\swoft\bin\swoft on line 7

Windows,Windows,Windows怎么搞,怎么搞,算了吧?

算了,整个问题关键环节在于流程上:

  1. 运行容器并设置共享目录,重点在于入口点选项。
$ docker run -d -i -t -p 80:80 -v /share/swoft:/var/www/swoft --privileged --entrypoint="" --name myswoft swoft/swoft /bin/bash

这里重点看下两个参数

  • --privileged 表示特权的意思,可以设置容器中的内核参数。使用该参数后容器内的root拥有真正的root权限,否则容器内的root只是外部的一个普通用户权限,privileged启动的容器可以查看到很多主机上的设备,并且可以执行mount挂载命令,甚至允许在容器中启动容器。
  • --entrypoint="" 表示重置容器的入口,默认swoft的入口程序是bin/swoft脚本文件,设置为空表示运行容器时不自动运行bin/swoft脚本,因为容器内swoft项目的依赖还没有安装,所以先启动容器然后进入容器安装依赖,最后再手工运行swoft项目。
  1. 进入容器下载安装配置swoft项目
$ docker exec -i -t swoft1 bash
root@2c546044f222:

就这样,我终于在设置共享目录成功的状态下开启了容器,爬起来了。不过,下一步又该如何呢?

未完待续...

推荐阅读更多精彩内容