I am trying to deploy an docker image, which is located inside the gitlab.com registry, to an external docker host. The docker host was created using docker-machine.

I am using a shared runner and the registry is private, so I will need to login first. To build the images and to run docker I'm using docker in docker.

Here is what I have so far:

---
services:
- name: docker:dind
  command: ["--experimental"]

stages:
#- build # Redacted
- deploy

variables:
  PHP_IMAGE_REF: ${CI_REGISTRY_IMAGE}/php:${CI_BUILD_REF_NAME}
  PHP_IMAGE_LATEST: ${CI_REGISTRY_IMAGE}/php:latest
  NGINX_IMAGE_REF: ${CI_REGISTRY_IMAGE}/nginx:${CI_BUILD_REF_NAME}
  NGINX_IMAGE_LATEST: ${CI_REGISTRY_IMAGE}/nginx:latest
  LETS_ENCRYPT_MAIL: "security@example.com"

# Cache composer dependencies
cache:
  paths:
  - api/vendor

#################################
##   Scripts for development   ##
#################################

# Deploy development to staging
deploy-staging:
  stage: deploy
  image: tmaier/docker-compose
  variables:
    SERVERNAME: staging.example.com
    EMAIL: $LETS_ENCRYPT_MAIL
    STAGE_DOCKER_HOST: "tcp://159.xxx.xxx.xxx:2376"
  cache: {}
  dependencies: []
  before_script:
  # Echo env vars for LetsEncrypt into .env
  - echo "VIRTUAL_HOST=$SERVERNAME" >> .env; echo "LETSENCRYPT_HOST=$SERVERNAME" >> .env; echo "LETSENCRYPT_EMAIL=$EMAIL" >> .env; echo "PHP_IMAGE=$PHP_IMAGE_REF" >> .env; echo "NGINX_IMAGE=$NGINX_IMAGE_REF" >> .env
  script:
  # Login to gitlab registry
  - docker login -u gitlab-ci-token -p ${CI_BUILD_TOKEN} registry.gitlab.com

  # Setup connection to server
  - mkdir -p ~/docker/certs
  - echo ${STAGE_CA} > ~/docker/certs/ca.pem
  - echo ${STAGE_CLIENT_CERT} > ~/docker/certs/cert.pem
  - echo ${STAGE_CLIENT_KEY} > ~/docker/certs/key.pem

  # Shutdown services
  - docker-compose --file docker-compose.prod.yml --verbose --host $STAGE_DOCKER_HOST --tlsverify --tlscacert ~/docker/certs/ca.pem --tlscert ~/docker/certs/cert.pem --tlskey ~/docker/certs/key.pem down -v

  # Remove old and pull new (nginx) image
  - docker rmi $NGINX_IMAGE_REF || echo "nginx image not exist"
  - docker pull $NGINX_IMAGE_REF

  # Remove old and pull new (php+app) image
  - docker rmi $PHP_IMAGE_REF || echo "php image not exist"
  - docker pull $PHP_IMAGE_REF

  # Recreate services
  - docker-compose--file docker-compose.prod.yml --verbose --host $STAGE_DOCKER_HOST --tlsverify --tlscacert ~/docker/certs/ca.pem --tlscert ~/docker/certs/cert.pem --tlskey ~/docker/certs/key.pem up -d
  environment:
    name: staging
    url: https://staging.example.com
  only:
  - development

Unfortunately does the above result in the following error and the pipeline does not succeed. When I run the command: docker-compose --file docker-compose.prod.yml --verbose --host $STAGE_DOCKER_HOST --tlsverify --tlscacert ~/docker/certs/ca.pem --tlscert ~/docker/certs/cert.pem --tlskey ~/docker/certs/key.pem down -v on my local windows machine it works using the same certificates.

urllib3.connectionpool._new_conn: Starting new HTTPS connection (1): 159.xxx.xxx.xxx
Traceback (most recent call last):
  File "/usr/bin/docker-compose", line 11, in <module>
    sys.exit(main())
  File "/usr/lib/python2.7/site-packages/compose/cli/main.py", line 71, in main
    command()
  File "/usr/lib/python2.7/site-packages/compose/cli/main.py", line 124, in perform_command
    project = project_from_options('.', options)
  File "/usr/lib/python2.7/site-packages/compose/cli/command.py", line 41, in project_from_options
    compatibility=options.get('--compatibility'),
  File "/usr/lib/python2.7/site-packages/compose/cli/command.py", line 121, in get_project
    host=host, environment=environment
  File "/usr/lib/python2.7/site-packages/compose/cli/command.py", line 95, in get_client
    version_info = six.iteritems(client.version())
  File "/usr/lib/python2.7/site-packages/docker/api/daemon.py", line 181, in version
    return self._result(self._get(url), json=True)
  File "/usr/lib/python2.7/site-packages/docker/utils/decorators.py", line 46, in inner
    return f(self, *args, **kwargs)
  File "/usr/lib/python2.7/site-packages/docker/api/client.py", line 198, in _get
    return self.get(url, **self._set_request_timeout(kwargs))
  File "/usr/lib/python2.7/site-packages/requests/sessions.py", line 521, in get
    return self.request('GET', url, **kwargs)
  File "/usr/lib/python2.7/site-packages/requests/sessions.py", line 508, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/lib/python2.7/site-packages/requests/sessions.py", line 618, in send
    r = adapter.send(request, **kwargs)
  File "/usr/lib/python2.7/site-packages/requests/adapters.py", line 506, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='159.xxx.xxx.xxx', port=2376): Max retries exceeded with url: /v1.30/version (Caused by SSLError(SSLError(0, u'unknown error (_ssl.c:3027)'),))
ERROR: Job failed: exit code 1

I'm farily new to devops, so:

  1. what options do I have?
  2. is there another/better way to deploy docker images to a remote docker host?
  3. ~could I solve the problem by using my own runner?~ Tried that. Results more or less in the same.

Note: As far as I understood does dind use the same docker version Ref.

  • 1
    - docker login -u gitlab-ci-token -p ${CI_BUILD_TOKEN} registry.gitlab.com Are you sure this worked for you? docs.gitlab.com/ee/ci/variables as per this documentation the variable names have changed. Can you try passing it in command line manually? – bi0s.kidd0 Oct 10 at 15:02
  • Thanks for pointing that out, unfortunately that wasn't it. – Tom Scholz Oct 10 at 15:26
  • Just in case, is your host and the dind image at the same version ? This looks like a cypher mismatch and I assume the dind image doesn't use the allowed cyphers on the remote host – Tensibai Oct 12 at 13:40
  • @Tensibai As far as I understood does dind use the same docker version. Ref: github.com/jpetazzo/dind#which-version-of-docker-does-it-run – Tom Scholz Oct 12 at 14:31
  • I won't swear, I'm still unsure why you need dind to use a remote host, I really can't find a reasons for that. But to debug further add a docker info at start of your script and check with the target host docker version – Tensibai Oct 12 at 16:14

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Browse other questions tagged or ask your own question.