docker下使用svn的hook实现精简版的自动部署

1.背景

网上有很多文章描述svn下如何使用hooks来实现自动化部署。本文侧重描述在docker环境的具体实现(其中也会包含非docker的实现方法)
相关环境:

  • svn的docker容器
  • 应用的docker容器
  • 宿主机本地目录
    • /XX/svn:存放svn相关配置、库数据
    • /XX/app:存放应用相关的程序、配置

2.SVN的配置修改

2.1.镜像

可通过【docker pull docker.io/elleflorio/svn-server:latest】下载一个svn的镜像,或者下载其他镜像,先按官方说明调试通过。

2.2.配置

2.2.1.SVN本地目录结构

/XX/svn的目录结构:

ubuntu@VM:~/svn$ ls -lrt
total 24
-rw-rw-r-- 1 ubuntu           ubuntu           384 May 11 22:17 dav_svn.conf
-rw-rw-r-- 1 ubuntu           ubuntu           125 May 11 22:24 passwd.conf
-rw-rw-r-- 1 ubuntu           ubuntu          1142 May 11 22:26 auth.conf
drwxr-xr-x 6 root             root            4096 May 11 22:26 seventy
-rwxrwxr-x 1 ubuntu           ubuntu           381 Jun  6 10:59 start.sh

其中seventy目录需在容器运行前先手工创建,然后在svn容器中执行svn建库命令,此目录只存放svn的库数据。
另外几个文件说明如下:

  • httpd的配置文件dav_svn.conf:
LoadModule dav_svn_module /usr/lib/apache2/mod_dav_svn.so
LoadModule authz_svn_module /usr/lib/apache2/mod_authz_svn.so
<Location /svn>
     DAV svn
     SVNParentPath /home/svn
     SVNListParentPath On
     AuthType Basic
     AuthName "Subversion Repository"
     AuthUserFile /home/svn/passwd.conf
     AuthzSVNAccessFile /home/svn/auth.conf 
     Require valid-user
</Location>

此项为针对apache的httpd配置,具体配置说明,可参考我的另一篇linux+httpd+svn实现http访问及修改口令,重点是其中的AuthUserFile和AuthzSVNAccessFile,其路径均指向/home/svn目录,此目录将会被挂载到宿主机上,因此/home/svn/passwd.conf也就是/XX/svn/passwd.conf,同理auth.conf。

  • SVN密码设置passwd.conf:
ubuntu@VM:~/svn$ cat passwd.conf
view:$apr1$/iL9B/Dn$UMyhxjh04gmtN7qSbo/K20

此文件需使用svn命令htpasswd生成,请不要手工编写。

  • SVN权限配置auth.conf:
[reps:/]
view=r

表示svn的URL中/svn/reps目录对view用户开放只读权限。读者可根据实际情况进行配置。

  • 容器启动脚本start.sh:
#!/bin/bash 
# 先后台启动容器
# 将svn和app的本地目录分别映射到容器的/home/svn和/home/app目录中
docker run --name svns \
-v /XX/svn:/home/svn \
-v /XX/app:/home/app \
-h svns \
-p 3380:80 \
-p 3360:3960 \
-m 305m \
-d docker.io/elleflorio/svn-server:latest
# 再在容器中执行一下配置数据命令
docker exec -d svns sh -c "cp /home/svn/dav_svn.conf /etc/apache2/conf.d/dav_svn.conf && chown -R apache:apache /home/app/"

说明:
1)启动容器时指定的参数,也可参考elleflorio/svn-server的官方说明,如果是其他镜像,请参考其具体的参数说明;
2)重点讲解下两个-v参数,前者是专用于存放svn自己的库文件、配置的目录,后者是专用于存放app的程序代码或配置,下节会详细说明。
3)最后的cp命令是将容器中已经存在的httpd配置进行覆盖,然后再修改/home/app目录的所属者为apache用户。

重点:需要修改/home/app为apache的所属者,原因为svn容器中实际执行时,是先通过apache用户来执行svn相关操作的,而不是容器默认的root用户,必须保证apache用户有权限往/home/app目录里写文件,否则后期的hooks在执行时就会出错。

2.2.2.钩子

前述操作完后,假设您已经调通svn了,可以通过http://<IP>:3380/svn/reps方式访问svn库了(可在浏览器中测试验证)。
下面开始真正的自动化部署实现。

  • 先在/XX/app或/home/app下创建程序包的复本
    svn co http://localhost:80/svn/reps  /home/app/ --username 'view' --password 'xxxxxx'
    

    上述是在svn容器中执行的,如果在宿主机上执行,则需修改下IP和端口。
    但无论如何,请记得在co完后,执行【chown -R apache:apache /home/app/】,因为默认这些文件的所属者多半不是apache的。

  • 编写钩子post-commit。
    将/home/svn/reps/hooks下的post-commit.tmpl复制一份,并重命名为post-commit:
    cd /home/svn/reps/hooks
    cp post-commit.tmpl  post-commit
    chown apache:apache post-commit   # 此步最好一起做下,以防万一
    chmod u+x post-commit
    touch /home/svn/hooks_commit.log  # 用来查看hook的执行日志
    chown apache:apache /home/svn/hooks_commit.log
    

    post-commit文件内容:

    ## 省略默认的模板部分
    TXN_NAME="$3"
    # mailer.py commit "$REPOS" "$REV" /path/to/mailer.conf
    logs="/home/svn/hooks_commit.log"  ## 此日志文件需有apache:apache写入权限,否则会看不到日志记录
    echo "${REPOS},${REV},${TXN_NAME}" >> ${logs}
    export LANG=en_US.utf8
    SVN_PATH="/usr/bin/svn"
    APP_PATH="/home/app/"
    ${SVN_PATH} update ${APP_PATH} --username 'view' --password 'xxxxxx' --no-auth-cache 1>>${logs} 2>&1
    echo "Updated. ${APP_PATH}" >> ${logs}
    

    此处重点是svn的update,与前文的svn的co形成前后呼应。
    可手工先验证下post-commit脚本是否有问题

    su -s /bin/sh -c '/home/svn/reps/hooks/post-commit' apache
    

    当然这个执行是在svn容器里面,表示使用apache用户和/bin/sh这个shell(如果镜像中有bash也可替换使用),来执行post-commit这个脚本,若在hooks_commit.log中未显示异常报错,则应该没有什么问题。

  • 验证hooks
    先【tail -f /home/svn/hooks_commit.log】,再随便在svn库中更新一个文件,看日志文件是否有更新,如果有报错,则改正。
  • 常见异常
    svn: E155004: Run 'svn cleanup' to remove locks (type 'svn help cleanup' for details)
    svn: E155004: Failed to lock working copy '/home/app'.
    svn: E200031: sqlite[S8]: attempt to write a readonly database
    svn: E200042: Additional errors:
    svn: E200031: sqlite[S8]: attempt to write a readonly database
    

    表明/home/app版本的所属者不是apache,请使用chown进行修改。

3.应用app

应用app可能有多种,假设您已经下载到一个合适的镜像,本文以python3.6+django2.0.5镜像为例,启动app镜像的start.sh

#!/bin/bash 
#
docker run --name app \
-v /XX/app:/datavol \
-h appserver \
-p 8089:8089 \
-m 500m \
--entrypoint /datavol/entrypoint-docker.sh \  # 重点
-d py365django205:latest  # app的镜像

其中/XX/app/entrypoint-docker.sh脚本如下:

#!/bin/sh
tail -f /dev/null

其实也就是不让容器停止而已,当然也可以编写自己的启动脚本。
对于django来说,当使用manage.py runserver方式来启动时,若程序代码有更新,django服务器会自动重启。
对于其他程序,读者可查阅相关文档,找到一种合理的方式去自动更新服务器状态。

4.完成

至此,所有的配置就已经完成了。当我们开发完代码,提交svn(http://xxx:xx/svn/reps/)完成后,svn容器就会主动去执行post-commit脚本,然后就会主动在/XX/app/目录下更新对应的工程代码,最后是应用app容器中自动重启服务,最终达到最精简的自动化部署的目的。

核心思想:通过宿主机的/XX/app目录来实现svn容器和app容器间代码的共享,形成生产者-消费者关系;/XX/app目录需apache用户权限。

    原文作者:tianxiawuzhe
    原文地址: https://www.jianshu.com/p/542d50824267
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞