如何持续构build版本化的Docker镜像

我有一个GitHub上的PHP项目,我想build立版本化的Docker镜像。 有点像CoreOS容器Linux与他们的阿尔法,testing版和稳定版本通道。

对于开发,我遵循Git Flow原则,并使用function – >开发 – >主分支。

我已经连接Travis进行自动PHPUnittesting,并且今天添加了CircleCI,因为我发现了可以自动生成版本的Rakefile。 它被用作标签。

我目前的.travis.yml:

--- services: - docker sudo: required env: global: - ... addons: jwt: secure: ... cache: directories: - /home/travis/docker/ before_install: - "docker --version" - 'if [[ ${TRAVIS_BRANCH} == "master" ]] && [[ ${TRAVIS_PULL_REQUEST} == "false" ]]; then echo "ENV GIT_SHA ${TRAVIS_COMMIT::8}" >> Dockerfile; fi' - 'if [[ ${TRAVIS_BRANCH} == "master" ]] && [[ ${TRAVIS_PULL_REQUEST} == "false" ]] && [[ -f ${DOCKER_CACHE_FILE} ]]; then gunzip -c ${DOCKER_CACHE_FILE} | docker load; fi' before_script: - "env > .env" install: - 'if [[ ${TRAVIS_BRANCH} == "master" ]] && [[ ${TRAVIS_PULL_REQUEST} == "false" ]]; then docker build -t ${DOCKER_REPOSITORY}:${TRAVIS_COMMIT::8} --pull=true .; fi' language: php notifications: slack: secure: ... php: - "5.6" script: - "phpunit --bootstrap tests/bootstrap.php --testdox tests --coverage-text" - 'if [[ ${TRAVIS_BRANCH} == "master" ]] && [[ ${TRAVIS_PULL_REQUEST} == "false" ]]; then mkdir -p $(dirname ${DOCKER_CACHE_FILE}) ; docker save $(docker history -q ${DOCKER_REPOSITORY}:${TRAVIS_COMMIT::8} | grep -v "<missing>") | gzip > ${DOCKER_CACHE_FILE}; fi' after_success: - 'if [[ $TRAVIS_PHP_VERSION == "5.6" ]] && [[ $TRAVIS_BRANCH == "develop" ]] && [[ $TRAVIS_PULL_REQUEST == "false" ]]; then sh generate-api.sh; fi' - 'if [[ ${TRAVIS_BRANCH} == "master" ]] && [[ ${TRAVIS_PULL_REQUEST} == "false" ]]; then docker login -u ${DOCKER_USERNAME} -p ${DOCKER_PASSWORD}; fi' - 'if [[ ${TRAVIS_BRANCH} == "master" ]] && [[ ${TRAVIS_PULL_REQUEST} == "false" ]]; then docker tag ${DOCKER_REPOSITORY}:${TRAVIS_COMMIT::8} ${DOCKER_REPOSITORY}:${TRAVIS_COMMIT::8}; fi' - 'if [[ ${TRAVIS_BRANCH} == "master" ]] && [[ ${TRAVIS_PULL_REQUEST} == "false" ]]; then docker tag ${DOCKER_REPOSITORY}:${TRAVIS_COMMIT::8} ${DOCKER_REPOSITORY}:travis-${TRAVIS_BUILD_NUMBER}; fi' - 'if [[ ${TRAVIS_BRANCH} == "master" ]] && [[ ${TRAVIS_PULL_REQUEST} == "false" ]]; then docker tag ${DOCKER_REPOSITORY}:${TRAVIS_COMMIT::8} ${AWS_ACCOUNT_NUMBER}.dkr.ecr.eu-west-1.amazonaws.com/${ECR_REPOSITORY}:${TRAVIS_COMMIT::8}; fi' - 'if [[ ${TRAVIS_BRANCH} == "master" ]] && [[ ${TRAVIS_PULL_REQUEST} == "false" ]]; then docker push ${DOCKER_REPOSITORY}; fi' - 'if [[ ${TRAVIS_BRANCH} == "master" ]] && [[ ${TRAVIS_PULL_REQUEST} == "false" ]]; then pip install --user awscli; fi' - 'if [[ ${TRAVIS_BRANCH} == "master" ]] && [[ ${TRAVIS_PULL_REQUEST} == "false" ]]; then export PATH=$PATH:$HOME/.local/bin; fi' - 'if [[ ${TRAVIS_BRANCH} == "master" ]] && [[ ${TRAVIS_PULL_REQUEST} == "false" ]]; then eval $(aws ecr get-login --region eu-west-1); fi' - 'if [[ ${TRAVIS_BRANCH} == "master" ]] && [[ ${TRAVIS_PULL_REQUEST} == "false" ]]; then docker push ${AWS_ACCOUNT_NUMBER}.dkr.ecr.eu-west-1.amazonaws.com/${ECR_REPOSITORY}:${TRAVIS_COMMIT::8}; fi' 

和我目前的circle.yml:

 --- machine: services: - docker php: version: 5.6.22 dependencies: override: - docker info - gem install httparty - rake build test: override: - mkdir -p $CIRCLE_TEST_REPORTS/phpunit - phpunit --bootstrap tests/bootstrap.php --log-junit $CIRCLE_TEST_REPORTS/phpunit/junit.xml tests - docker run -d -p 9000:9000 storecore/php:latest; sleep 10 - nc -z -w5 localhost 9000 

和使用的Rakefile:

 require 'rake' require 'httparty' require 'json' # Read the base version from VERSION file. def version file = File.readlines('./version.php') v = file[1].scan(/'([^']*)'/) v[1].join(",") end # The name of the container def container_name 'php' end # The username the container is pushed to on DockerHub def username 'storecore' end # Get the latest version for the given base version provided by #version def hub_version base = version taginfo = JSON.parse(HTTParty.get("https://hub.docker.com/v2/repositories/#{username}/#{container_name}/tags/").body)['results'] return { base: base, build: nil } if taginfo.nil? tags = [] taginfo.each do |tag| tags << tag['name'] end current_base = tags.grep(/#{base}/) return { base: base, build: nil } if current_base.empty? build = current_base.sort { |x, y| a = x.split('.')[base.split('.').count].to_i b = y.split('.')[base.split('.').count].to_i a <=> b }.last.split('.').last.to_i { base: base, build: build } end # return current hub version for the current base def latest_hub_version latest = hub_version "#{latest[:base]}.#{latest[:build]}" end # return the next version for the current base def next_version latest = hub_version base = version build = latest[:build] || -1 build += 1 "#{base}.#{build}" end task :install_deps do sh 'gem install bundler' sh 'bundle install' end desc 'login into Docker Hub' task :login do sh "docker login -u #{ENV['DOCKER_USER']} -p #{ENV['DOCKER_PASS']}" end desc 'tags latest as next_version' task :tag => :login do sh "docker tag #{username}/#{container_name}:latest #{username}/#{container_name}:#{next_version}" end desc 'pushes the next_version and latest to docker hub' task :push => :tag do sh "docker push #{username}/#{container_name}:#{next_version}" sh "docker push #{username}/#{container_name}:latest" end desc 'builds as latest' task :build => :install_deps do sh "docker build --rm=false -t #{username}/#{container_name}:latest ." end task default: [:build, :push] 

但最终,两种解决scheme都不能为我提供每个发布版本的Docker镜像,并且以各自的方式受到限制。 这对我来说看起来很不舒服。 我敢打赌,有更好的方法或工具,我可以使用。 我不介意完全转向别的东西。

CoreOS做什么是最好的方法?