应用开发入门

基于 OpenPitrix 开发规范,平台旨在帮助软件开发者以极低的学习成本快速部署自己的传统应用到多云的运行环境中并提供一站式的平台方便管理用户的资源和环境,本文通过以下开发示例开发一个 Wordpress 应用,以及上传到平台并部署到基于 VM 的云运行时环境中,帮助开发者熟悉 OpenPitrix 应用开发的规范和流程。

制作镜像

WordPress 后端存储需要依赖数据库,实例使用的 MySQL 数据库,该应用需要创建 2 个 docker 镜像。

第一步:制作 mysql 镜像

由于需要实现配置变更及管理组件的自动升级,不能直接使用已有的 docker 镜像,需要进行一些改造,Docker 镜像默认启动的进程不能是应用本身的进程,而应该是 supervisor,由 supervisor 来启动 drone 服务。

1、将 drone 和 nsenter 添加到镜像,然后安装 supervisor 并进行适当的配置。

  • drone 是 OpenPitrix 的 Agent 服务,与 OpenPitrix 调度系统进行交互。
  • nsenter 用来在 Docker 内进入 Host 执行一些指令,比如挂载硬盘、ssh 免密登录等。
  • supervisor 用来为 drone 的自动升级提供支持服务。可在制作 Docker 镜像时从 openpitrix/openpitrix:metadata 镜像中拷贝获取 drone 和 nsenter 这两个可执行文件以及 supervisor 相关的启动脚本:

Dockerfile

  1. FROM mysql:5.6
  2. COPY --from=openpitrix/openpitrix:metadata /usr/local/bin/drone /usr/local/bin/
  3. COPY --from=openpitrix/openpitrix:metadata /usr/bin/nsenter /usr/bin/
  4. RUN apt-get update && apt-get install -y supervisor
  5. COPY --from=openpitrix/openpitrix:metadata /etc/supervisor.d/drone.ini /etc/supervisor/conf.d/drone.conf
  6. COPY --from=openpitrix/openpitrix:metadata /usr/local/bin/start-drone.sh /usr/local/bin/start-drone.sh
  7. COPY start-supervisord.sh /usr/local/bin/
  8. ENTRYPOINT ["start-supervisord.sh"]

其中 start-supervisord.sh 的内容如下:

  1. #!/bin/sh
  2. exec supervisord -n

2、制作 MySQL 镜像并上传到镜像仓库,请预先准备好 Docker 镜像仓库( ${registry} 替换为您实际的镜像仓库的名字)。

  1. $ docker build -t ${registry}/mysql .
  2. $ docker push ${registry}/mysql

第二步:制作 Wordpress 镜像

1、创建模板文件。制作镜像需要开发一些必须的模版文件,这些文件会监听 metadata service 的变化从而更新自己应用的配置文件。这些文件后缀名为 toml 和 tmpl,其中后缀名为 toml 的文件位于 /etc/confd/conf.d/ 目录下,后缀名为 tmpl 的文件位于 /etc/confd/templates/ 目录下。

conf.d/mysql_hostname.toml

  1. [template]
  2. src = "mysql_hostname.tmpl"
  3. dest = "/opt/openpitrix/conf/mysql_hostname"
  4. keys = [
  5. "/",
  6. ]

说明:toml 文件中, src 代表模版文件名,dest 即应用的配置文件,这个配置文件会根据 src 模版刷新 dest 内容,keys 即进程 confd 监控 QingCloud metadata service 关于该节点所在集群信息的更新,有变化则更新,如果模版中需要用到某个 key 的信息,则需要监听这个 key,也可以直接监听根目录”/”。reloadcmd 则是配置文件被刷新后的操作,脚本开发者自行提供脚本,如果不需要触发动作可以去掉 reloadcmd 这一行。toml 文件里可加上权限控制 比如 uid,gid,mode 等。

templates/mysql_hostname.tmpl

  1. {{range $dir := lsdir "/hosts/Mysql/"}}{{$ip := printf "/hosts/Mysql/%s/ip" $dir}}{{getv $ip}}{{end}}

说明:tmpl 模版文件决定应用配置文件内容。drone 读取 metadata service 并刷新这些变量的值,如此例 range 这一行是读取 Mysql 节点的 IP 信息。了解更多参见 libconfd

2、新建目录,并将上一步准备的两个模板文件拷贝到 /etc/confd/ 目录下。然后,可在制作 Docker 镜像时从 openpitrix/openpitrix:metadata 镜像中拷贝获取 drone 和 nsenter 可执行文件以及 supervisor 相关的启动脚本:

Dockerfile

  1. FROM wordpress
  2. COPY --from=openpitrix/openpitrix:metadata /usr/local/bin/drone /usr/local/bin/
  3. COPY --from=openpitrix/openpitrix:metadata /usr/bin/nsenter /usr/bin/
  4. RUN apt-get update && apt-get install -y supervisor
  5. COPY --from=openpitrix/openpitrix:metadata /etc/supervisor.d/drone.ini /etc/supervisor/conf.d/drone.conf
  6. COPY --from=openpitrix/openpitrix:metadata /usr/local/bin/start-drone.sh /usr/local/bin/start-drone.sh
  7. COPY start-supervisord.sh /usr/local/bin/
  8. ENTRYPOINT ["start-supervisord.sh"]
  9. RUN mkdir -p /etc/confd/conf.d/
  10. RUN mkdir -p /etc/confd/templates/
  11. COPY conf.d/* /etc/confd/conf.d/
  12. COPY templates/* /etc/confd/templates/

3、制作 Wordpress 镜像并上传到镜像仓库,请预先准备好 Docker 镜像仓库( ${registry} 替换为您实际的镜像仓库的名字)。

  1. $ docker build -t ${registry}/wordpress .
  2. $ docker push ${registry}/wordpress

准备应用配置包

第一步:准备 OpenPitrix 客户端工具

以下命令默认下载最新的客户端工具,拷贝文件到指定的 bin 目录。以 v0.2.3 为例,执行命令时应替换为实际的下载版本号:

  1. $ curl -L https://git.io/GetOpenPitrixBin | sh -
  2. $ cd openpitrix-v0.2.3-bin/
  3. $ cp * /usr/local/bin/

第二步:创建应用目录

  1. $ mkdir Wordpress

第三步:准备配置文件

其中 cluster.json.tmpl,config.json,package.json 这三个配置文件是必须的,详见 开发模板规范

Wordpress/cluster.json.tmpl

  1. {
  2. "name": "{{.cluster.name}}",
  3. "description": "{{.cluster.description}}",
  4. "subnet": "{{.cluster.subnet}}",
  5. "nodes": [
  6. {
  7. "role": "Mysql",
  8. "container": {
  9. "type": "docker",
  10. "image": "${registry}/mysql"
  11. },
  12. "count": 1,
  13. "cpu": "{{.cluster.Mysql.cpu}}",
  14. "memory": "{{.cluster.Mysql.memory}}",
  15. "services": {
  16. "start": {
  17. "cmd": "MYSQL_ROOT_PASSWORD=wordpress MYSQL_ROOT_HOST=% docker-entrypoint.sh mysqld & sleep 10"
  18. }
  19. }
  20. },
  21. {
  22. "role": "Wordpress",
  23. "container": {
  24. "type": "docker",
  25. "image": "${registry}/wordpress"
  26. },
  27. "count": 1,
  28. "cpu": "{{.cluster.Wordpress.cpu}}",
  29. "memory": "{{.cluster.Wordpress.memory}}",
  30. "services": {
  31. "start": {
  32. "order": 1,
  33. "cmd": "WORDPRESS_DB_PASSWORD=wordpress WORDPRESS_DB_HOST=`cat /opt/openpitrix/conf/mysql_hostname` docker-entrypoint.sh apache2-foreground & sleep 10"
  34. }
  35. }
  36. }
  37. ]
  38. }

Wordpress/config.json

  1. {
  2. "type": "array",
  3. "properties": [
  4. {
  5. "key": "cluster",
  6. "description": "WORDPRESS properties",
  7. "type": "array",
  8. "properties": [
  9. {
  10. "key": "name",
  11. "label": "name",
  12. "description": "The name of the WORDPRESS service",
  13. "type": "string",
  14. "default": "Wordpress",
  15. "required": false
  16. },
  17. {
  18. "key": "description",
  19. "label": "description",
  20. "description": "The description of the WORDPRESS service",
  21. "type": "string",
  22. "default": "",
  23. "required": false
  24. },
  25. {
  26. "key": "subnet",
  27. "label": "Subnet",
  28. "description": "Choose a subnet to join",
  29. "type": "string",
  30. "default": "",
  31. "required": true
  32. },
  33. {
  34. "key": "Mysql",
  35. "label": "Mysql",
  36. "description": "MySql properties",
  37. "type": "array",
  38. "properties": [
  39. {
  40. "key": "cpu",
  41. "label": "CPU",
  42. "description": "CPUs of each node",
  43. "type": "integer",
  44. "default": 1,
  45. "range": [1,2,4,8,16],
  46. "required": true
  47. },
  48. {
  49. "key": "memory",
  50. "label": "Memory",
  51. "description": "memory of each node (in MB)",
  52. "type": "integer",
  53. "default": 2048,
  54. "range": [2048,8192,16384,32768,49152],
  55. "required": true
  56. }
  57. ]
  58. },
  59. {
  60. "key": "Wordpress",
  61. "label": "Wordpress",
  62. "description": "Wordpress properties",
  63. "type": "array",
  64. "properties": [
  65. {
  66. "key": "cpu",
  67. "label": "CPU",
  68. "description": "CPUs of each node",
  69. "type": "integer",
  70. "default": 1,
  71. "range": [1,2,4],
  72. "required": true
  73. },
  74. {
  75. "key": "memory",
  76. "label": "Memory",
  77. "description": "memory of each node (in MB)",
  78. "type": "integer",
  79. "default": 1024,
  80. "range": [1024,2048,4096],
  81. "required": true
  82. }
  83. ]
  84. }
  85. ]
  86. }
  87. ]
  88. }

Wordpress/package.json

  1. {
  2. "api_version":"v1",
  3. "name":"Wordpress",
  4. "version":"0.1.0",
  5. "app_version":"4.9.7",
  6. "keywords": [
  7. "wordpress",
  8. "blog",
  9. "http",
  10. "web",
  11. "application",
  12. "php",
  13. "cms"
  14. ],
  15. "description":"Web publishing platform for building blogs and websites.",
  16. "icon": "https://openpitrix.pek3a.qingstor.com/icon/wordpress_icon.png",
  17. "home": "http://www.wordpress.com/",
  18. "maintainers": [
  19. {
  20. "email": "openpitrix@yunify.com",
  21. "name": "openpitrix"
  22. }
  23. ],
  24. "screenshots": [
  25. "https://openpitrix.pek3a.qingstor.com/icon/wordpress_snapshot1.png",
  26. "https://openpitrix.pek3a.qingstor.com/icon/wordpress_snapshot2.png"
  27. ]
  28. }

第四步:打包应用

回到 Wordpress 上级目录,执行打包命令:

  1. $ op package Wordpress
  2. Successfully packaged app and saved it to: /root/test/Wordpress-0.1.0.tgz
  3. $ ls
  4. Wordpress Wordpress-0.1.0.tgz

打包后,可以看到将生成一个 Wordpress-0.1.0.tgz 配置包,然后将该配置包上传到 OpenPitrix 平台,参见 开发者 - 上传应用