docker-compose概念
Docker Compose 是 Docker 官方编排(Orchestration)项目之一,负责快速在集群中部署分布式应用。
教程
本文算不上教程,主要是记录一下个人在这块的实践,防止哪天忘了,翻翻博客还能找的回。不过不排除有人需要详细的成体系的教程,这个放个地址 。
笔记
Gitlab
svn在阿里云,而且磁盘满了有时候都没法提交,备份也没法备份,最后决定把版本控制迁回来,使用git-svn转换以后,最终把svn替换为git。所以要搭建一个gitlab服务器。前任团队的坑。。。
docker-compose.yml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
| version: '2'
services: redis: restart: always image: sameersbn/redis:latest command: - --loglevel warning volumes: - /srv/docker/gitlab/redis:/var/lib/redis:Z
postgresql: restart: always image: sameersbn/postgresql:9.5-1 volumes: - /srv/docker/gitlab/postgresql:/var/lib/postgresql:Z environment: - DB_USER=gitlab - DB_PASS=password - DB_NAME=gitlabhq_production - DB_EXTENSION=pg_trgm
gitlab: restart: always image: sameersbn/gitlab:8.11.5 depends_on: - redis - postgresql ports: - "10080:80" - "10022:22" volumes: - /srv/docker/gitlab/gitlab:/home/git/data:Z environment: - DEBUG=false
- DB_ADAPTER=postgresql - DB_HOST=postgresql - DB_PORT=5432 - DB_USER=gitlab - DB_PASS=password - DB_NAME=gitlabhq_production
- REDIS_HOST=redis - REDIS_PORT=6379
- TZ=Asia/Shanghai - GITLAB_TIMEZONE=Kolkata
- GITLAB_HTTPS=false - SSL_SELF_SIGNED=false
- GITLAB_HOST=116.7.245.195 - GITLAB_PORT=10080 - GITLAB_SSH_PORT=10022 - GITLAB_RELATIVE_URL_ROOT= - GITLAB_SECRETS_DB_KEY_BASE=safausdlfjkj23k4jkljslkdfjlkjasdlkfu8u234ioj23krjlsdfjasdfjkasdfk - GITLAB_SECRETS_SECRET_KEY_BASE=sadfkljiwfjsnscjksdhfuwehnfnsaldfjh3rhljsdkfjlksajdf - GITLAB_SECRETS_OTP_KEY_BASE=asfdlaxzcvnhwefhweoicnmcsflncnzmxbvsdajkfasdsdnfkjhsadfj
- GITLAB_ROOT_PASSWORD=edeh123456 - GITLAB_ROOT_EMAIL=que01@foxmail.com
- GITLAB_NOTIFY_ON_BROKEN_BUILDS=true - GITLAB_NOTIFY_PUSHER=false
- GITLAB_EMAIL=notifications@example.com - GITLAB_EMAIL_REPLY_TO=noreply@example.com - GITLAB_INCOMING_EMAIL_ADDRESS=reply@example.com
- GITLAB_BACKUP_SCHEDULE=daily - GITLAB_BACKUP_TIME=01:00
- SMTP_ENABLED=false - SMTP_DOMAIN=www.example.com - SMTP_HOST=smtp.gmail.com - SMTP_PORT=587 - SMTP_USER=mailer@example.com - SMTP_PASS=password - SMTP_STARTTLS=true - SMTP_AUTHENTICATION=login
- IMAP_ENABLED=false - IMAP_HOST=imap.gmail.com - IMAP_PORT=993 - IMAP_USER=mailer@example.com - IMAP_PASS=password - IMAP_SSL=true - IMAP_STARTTLS=false
- OAUTH_ENABLED=false - OAUTH_AUTO_SIGN_IN_WITH_PROVIDER= - OAUTH_ALLOW_SSO= - OAUTH_BLOCK_AUTO_CREATED_USERS=true - OAUTH_AUTO_LINK_LDAP_USER=false - OAUTH_AUTO_LINK_SAML_USER=false - OAUTH_EXTERNAL_PROVIDERS=
- OAUTH_CAS3_LABEL=cas3 - OAUTH_CAS3_SERVER= - OAUTH_CAS3_DISABLE_SSL_VERIFICATION=false - OAUTH_CAS3_LOGIN_URL=/cas/login - OAUTH_CAS3_VALIDATE_URL=/cas/p3/serviceValidate - OAUTH_CAS3_LOGOUT_URL=/cas/logout
- OAUTH_GOOGLE_API_KEY= - OAUTH_GOOGLE_APP_SECRET= - OAUTH_GOOGLE_RESTRICT_DOMAIN=
- OAUTH_FACEBOOK_API_KEY= - OAUTH_FACEBOOK_APP_SECRET=
- OAUTH_TWITTER_API_KEY= - OAUTH_TWITTER_APP_SECRET=
- OAUTH_GITHUB_API_KEY= - OAUTH_GITHUB_APP_SECRET= - OAUTH_GITHUB_URL= - OAUTH_GITHUB_VERIFY_SSL=
- OAUTH_GITLAB_API_KEY= - OAUTH_GITLAB_APP_SECRET=
- OAUTH_BITBUCKET_API_KEY= - OAUTH_BITBUCKET_APP_SECRET=
- OAUTH_SAML_ASSERTION_CONSUMER_SERVICE_URL= - OAUTH_SAML_IDP_CERT_FINGERPRINT= - OAUTH_SAML_IDP_SSO_TARGET_URL= - OAUTH_SAML_ISSUER= - OAUTH_SAML_LABEL="Our SAML Provider" - OAUTH_SAML_NAME_IDENTIFIER_FORMAT=urn:oasis:names:tc:SAML:2.0:nameid-format:transient - OAUTH_SAML_GROUPS_ATTRIBUTE= - OAUTH_SAML_EXTERNAL_GROUPS= - OAUTH_SAML_ATTRIBUTE_STATEMENTS_EMAIL= - OAUTH_SAML_ATTRIBUTE_STATEMENTS_NAME= - OAUTH_SAML_ATTRIBUTE_STATEMENTS_FIRST_NAME= - OAUTH_SAML_ATTRIBUTE_STATEMENTS_LAST_NAME=
- OAUTH_CROWD_SERVER_URL= - OAUTH_CROWD_APP_NAME= - OAUTH_CROWD_APP_PASSWORD=
- OAUTH_AUTH0_CLIENT_ID= - OAUTH_AUTH0_CLIENT_SECRET= - OAUTH_AUTH0_DOMAIN=
- OAUTH_AZURE_API_KEY= - OAUTH_AZURE_API_SECRET= - OAUTH_AZURE_TENANT_ID=
|
gitlab的docker-compose配置文件其实直接从官方拿过来用的。虽然没什么太大参考价值。不过这里用到了常用的选项,比如restart,image,command,volumes,environment,depends_on。
各个配置项的作用:
- restart 当容器意外退出后是否自动再次重新启动
- image 容器镜像
- command 容器启动后执行的命令
- volumes 挂载卷,将本地的磁盘目录挂在到容器内 主要做数据备份用
- environment 环境变量配置
- depends_on 依赖项,这个配置可以确保依赖服务被配置,但是并不能保证启动顺序
Rap
淘宝的rap是个很不错的东西。前后端分离时候最麻烦的东西就是文档&&文档维护。加上rap本身的数据mock功能,这是一个杀手锏。
rap的docker-compose配置在github上找到一个不错的。srzyhead/rap,不过mysql的配置有点问题导致数据统计没法用,跑过去提了一下pull request。现在没啥问题了,直接git clone回来,按照readme操作即可。
mysql
这个没用到docker-compose,简单的运行了
1 2
| mkdir data docker run --name mysql -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_USER=lyshow -e MYSQL_PASSWORD=123456 -p 3306:3306 -v $(pwd)/data:/var/lib/mysql -d mysql:5.6 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
|
java项目部署
主要是两个类型的历史项目,一个基于ant打包的,一个是基于maven打包的项目。
ant项目
配置目录:
1 2 3 4 5
| . ├── docker-compose.yml ├── server.xml ├── tomcat7 └── wait-for-file.sh
|
docker-compose.yml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| version: '2'
services: ant-test: image: frekele/ant:1.9.7-jdk7 volumes: - ./tomcat7/:/usr/local/tomcat/:Z - ../../hotdoc/pc/test/:/data/:Z entrypoint: | bash -c "rm -f /data/done && rm -rf /data/WebRoot/WEB-INF/classes && mkdir -p /data/WebRoot/WEB-INF/classes && ant -f /data/build.xml && touch /data/done"
tomcat-test: image: openweb/oracle-tomcat:7-jre7 command: ["bin/catalina.sh", "run"] depends_on: - ant-test-test entrypoint: /tool/wait-for-file.sh /data/done ports: - "9088:800" volumes: - ./wait-for-file.sh:/tool/wait-for-file.sh - ./server.xml:/usr/local/tomcat/conf/server.xml - ../../hotdoc/pc/test/:/data/:Z
|
主要是用到了两个服务,一个编译服务,一个tomcat。
server.xml和tomcat7就不说了,主要是项目依赖。主要需要注意的是wait-for-file.sh这个,前面已经说到了,depends_on可以配置依赖项,但是并没有办法确保依赖服务器在主服务就绪前就绪,所以就有了wait-for-file.sh这个东西。
wait-for-file.sh里面东西很简单:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #!/bin/bash
set -e
waitFile="$1" shift cmd="$@"
until test -e $waitFile do >&2 echo "Waiting for file [$waitFile]." sleep 1 done
>&2 echo "Found file [$waitFile]." exec $cmd
|
主要逻辑就是利用文件的存在来判断是否执行一个操作。这个东西似乎从stackoverflow找到的,非专业只管用就是了。
例子在上面已经有了,entrypoint里面进行wait,然后command里面执行最终要执行的命令。编译服务在启动之前要记住需要删除这个作为flag的done文件。
mvn项目
mvn的项目和ant的是一个思路,一个编译服务,一个tomcat
配置结构:
1 2 3 4
| . ├── docker-compose.yml ├── server.xml └── wait-for-file.sh
|
docker-compose.yml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| version: '2'
services: mvn-test-ios: image: maven:3.2.3-jdk-7u65 volumes: - ../../../hotdoc/mobile/test_ios:/data/:Z - ~/.m2/:/root/.m2/ entrypoint: | bash -c "rm -rf /data/done && cd /data && mvn clean install -Dmaven.test.skip=true && echo '############test_ios mvn clean install is ok ##############' && touch /data/done"
tomcat-test-ios: image: openweb/oracle-tomcat:7-jre7 command: ["bin/catalina.sh", "run"] depends_on: - mvn-test-ios entrypoint: /tool/wait-for-file.sh /data/done environment: - LANG=zh_CN.UTF-8 - TZ=Asia/Shanghai ports: - "9001:800" volumes: - ./wait-for-file.sh:/tool/wait-for-file.sh - ./server.xml:/usr/local/tomcat/conf/server.xml - ../../../hotdoc/mobile/test_ios:/data/:Z
|
思路和ant的一模一样,只不过编译服务器换成了mvn的,mvn编译时候需要下载过多的依赖,为了省事省时,做了个磁盘映射: ~/.m2/:/root/.m2/ 这样可以高效利用缓存,重启服务器也不会又要再次下载依赖了。
react的项目
以上项目是历史项目,不过最近做了一个完全前后端分离的的react为基础的项目。因为用到了react-router,所以需要对nginx做一些配置才能正常运行。后端的代码依然是基于java的,构建工具是maven。
配置结构:
1 2 3 4 5
| . ├── docker-compose.yml ├── nginx.conf ├── server.xml └── wait-for-file.sh
|
docker-compose.yml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| version: '2'
services: mvn-opeartion: image: maven:3.2.3-jdk-7u65 volumes: - ../../hotdoc/operation/lyshows:/data/:Z - ~/.m2/:/root/.m2/ entrypoint: | bash -c "rm -rf /data/done && cd /data && mvn clean install -Dmaven.test.skip=true && echo '############test_opeartion mvn clean install is ok ##############' && touch /data/done"
tomcat-operation: image: openweb/oracle-tomcat:7-jre7 command: ["bin/catalina.sh", "run"] entrypoint: /tool/wait-for-file.sh /data/done environment: - LANG=zh_CN.UTF-8 - TZ=Asia/Shanghai ports: - "9003:800" volumes: - ./wait-for-file.sh:/tool/wait-for-file.sh - ./server.xml:/usr/local/tomcat/conf/server.xml - ../../hotdoc/operation/lyshows:/data/:Z
nginx: image: nginx:stable-alpine restart: always ports: - 7776:8888 - 443:443 links: - tomcat-operation:backend volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro - ../../hotdoc/operation/frontEnd/dist:/usr/share/nginx/html/dist
|
nginx.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| worker_processes 1;
events { worker_connections 1024; }
error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid;
http { include /etc/nginx/mime.types; default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on; #tcp_nopush on;
keepalive_timeout 65;
# 开启gzip gzip on;
# 启用gzip压缩的最小文件,小于设置值的文件将不会压缩 gzip_min_length 1k;
# gzip 压缩级别,1-10,数字越大压缩的越好,也越占用CPU时间,后面会有详细说明 gzip_comp_level 6;
# 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。 gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
# 是否在http header中添加Vary: Accept-Encoding,建议开启 gzip_vary on;
server { listen 8888; server_name ""; root /usr/share/nginx/html/dist;
gzip_static on;
location / { try_files $uri $uri/ /index.html; }
location /api { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://backend:800/; } } }
|
server.xml是tomcat的配置,这里主要依托后端项目,但是这也不是重点,所以也不贴了。
小结
目前docker和docker-compose主要是用在了公司的开发服务上面,3个月来主要是刚开始gitlab宕机了一次,重启之后数据毫无影响,整体体验还是非常不错的。
而且依托docker,这一套环境在几天之内就完全搭建起来,而且没有污染宿主机器环境,个人感觉非常不错。
遗留问题
docker-compose内部容器访问宿主机器端口尚未找到办法。
PS: 在此文正式发布之前,已经找到了解决方案:那就是external_links选项;但是external_links存在的问题是两个容器之间必须有共通的网络才行,而默认使用docker启动的docker容器似乎是bridge,所以这里需要设置network选项为bridge才行。
当然,说了这么多,如果没有代码其实还是很不好理解。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| tomcat-operation: image: openweb/oracle-tomcat:7-jre7 command: ["bin/catalina.sh", "run"] entrypoint: /tool/wait-for-file.sh /data/done network_mode: "bridge" environment: - LANG=zh_CN.UTF-8 - TZ=Asia/Shanghai ports: - "9003:800" volumes: - ./wait-for-file.sh:/tool/wait-for-file.sh - ./server.xml:/usr/local/tomcat/conf/server.xml - ../../hotdoc/operation/lyshows:/data/:Z external_links: - mysql:mysql
nginx: image: nginx:stable-alpine restart: always network_mode: "bridge" ports: - 7776:8888 - 443:443 links: - tomcat-operation:backend volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro - ../../hotdoc/operation/frontEnd/dist:/usr/share/nginx/html/dist
|