Docker 服务未在 Ansible 中启动
Docker service is not started in Ansible
我正在学习 Ansible
,想在我的笔记本电脑上本地使用它,目前我正在使用 "includes"。
我想准备一个剧本来导入一些其他任务(安装基础包,设置 git、vim 和 docker)并执行它。
All the code is hosted in GitLab
and I'm using their free CI
service to test the plays.
CI 作业将 运行 直到检查 docker
服务是否 运行ning。此时,播放将失败并显示以下消息:
fatal: [localhost]: FAILED! => {
"changed": true,
"cmd": ["service", "docker", "restart"],
"delta": "0:00:00.176233",
"end": "2017-09-28 18:49:56.194752",
"failed": true,
"msg": "non-zero return code",
"rc": 1,
"start": "2017-09-28 18:49:56.018519",
"stderr": "",
"stderr_lines": [],
"stdout": "",
"stdout_lines": []
}
我在我的笔记本电脑上创建了一个 docker 容器 (docker run --rm -ti debian
) 并在本地执行了播放,但它在同一个地方失败了。
但是,如果容器是用privileged
标志创建的,我可以手动启动服务,然后重新执行播放。这一次,它会成功完成。
所以,我的问题是:
- 如何使用
Ansible
启动 docker
服务?
- 我是不是完全错了,还有更好的方法来实现它吗?
- 当 运行 在我的笔记本电脑中安装容器时,我在
privilege
模式下创建了它。这允许我手动启动服务。
- 因为我无法修改在
GitLab-CI
public 实例中创建容器的方式:
- 在启用
privileged
标志的情况下,将我自己的 运行ner 添加到项目中可能是一个可行的解决方案吗?
PS: 目前,我并不是在研究最佳实践,我只是想让这个 运行 有所作为一起玩。
环境:
- Ansible:2.4.0
- Python: 2.7.13
- Docker: 17.09.0-ce
--- --- ---
gitlab-ci.yml
文件:
image: debian:latest
variables:
HOST_INVENTORY: "./hosts"
INCLUDES_DIR: "./gists/includes"
before_script:
- apt-get update -qq
- apt-get install -y curl gcc g++ openssh-server openssh-client python python-dev python-setuptools libffi-dev libssl-dev
- easy_install pip
- pip install ansible
stages:
- syntax_check
- install
check:
stage: syntax_check
script:
- ansible-playbook -i $HOST_INVENTORY $INCLUDES_DIR/play.yml --limit 'local' --syntax-check;
run_includes:
stage: install
script:
- ANSIBLE_PIPELINING=True ansible-playbook -i $HOST_INVENTORY $INCLUDES_DIR/play.yml --limit 'local';
play.yml
很简单,只导入了一些剧本:
- hosts: local
become: yes
become_method: sudo
pre_tasks:
- import_tasks: tasks/pre.yml # update package manager cache
tasks:
- import_tasks: tasks/common.yml
- import_tasks: tasks/docker.yml
和 docker
任务:
- name: Dependencies
package:
name: "{{ item }}"
state: installed
with_items:
- apt-transport-https
- ca-certificates
- curl
- gnupg2
- software-properties-common
- name: Docker module dependencies
pip:
name: docker-py
- name: Add Docker key
shell: curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg | apt-key add -
- name: Add Docker repo
shell: echo "deb [arch=amd64] https://download.docker.com/linux/$(. /etc/os-release; echo $ID) $(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list
- name: Install Docker
apt:
pkg: docker-ce
state: installed
update_cache: yes
- name: Ensure Docker group is present
group:
name: docker
state: present
- name: Add current user to the Docker group
user:
name: "{{ ansible_user }}"
groups:
- docker
append: yes
- name: Ensure service is enabled
command: service docker restart
- name: Pull images from Docker hub
docker_image:
name: "{{ item }}"
with_items:
- debian
- cern/cc7-base
所以我在 gitlab.com
上创建了一个示例项目,其中 运行s 在 运行ner
上的几个命令
$ echo PWD is $PWD
PWD is /builds/tarunlalwani/testci
$ id
uid=0(root) gid=0(root) groups=0(root)
$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.1 20260 2984 ? Ss 19:41 0:00 /bin/bash
root 7 0.0 0.1 20420 2652 ? S 19:41 0:00 /bin/bash
root 10 0.0 0.0 17500 1996 ? R 19:41 0:00 ps aux
$ which systemctl
/bin/systemctl
$ systemctl status docker
Failed to get D-Bus connection: Unknown error -1
ERROR: Job failed: exit code 1
如您所见,我们 运行 在一个容器中,因此您的 ansible 脚本将无法运行。没有要启动或结束的 docker 服务。此外,由于您在 docker 容器内,重新启动 docker 容器也意味着终止您正在 运行 的容器。
您需要设置一个 Ubuntu VM,然后在其上设置带有 Shell 执行程序的 Gitlab Runner。 shell 执行器意味着您在该 VM 上的命令 运行,它将具有 systemctl
和 docker
服务
另一种方法是使用 GitLab's dind
service,这样我们就可以使用已经提供的共享 运行ners 在容器内测试 playbook。
这里需要两件事:
- A
Dockerfile
在哪里构建一个基础镜像,满足 运行 Ansible 的所有要求。
- 将
gitlab-ci
文件修改为 运行 容器内的作业。
例如,Dockerfile
可能如下所示:
FROM debian:latest
ARG USERNAME
RUN apt-get update && \
apt-get install -y curl \
git \
gcc \
g++ \
libffi-dev \
libssl-dev \
openssh-client \
openssh-server \
python \
python-dev \
python-setuptools \
sudo
RUN easy_install pip && \
pip install ansible \
jmespath
RUN useradd -ms /bin/bash $USERNAME
USER $USERNAME
WORKDIR /home/$USERNAME
然后,在 gitlab-ci.yml
文件中,我们可以有如下内容:
image: docker:latest
services:
- docker:dind
variables:
DOCKER_IMAGE: "registry.gitlab.com/<YOUR_USER>/<YOUR_REPO>/dummy-image"
CONTAINER_NAME: "test"
IMAGE_USERNAME: "dummy"
stages:
- build
- check
before_script:
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.gitlab.com
after_script:
- docker rm -f $(docker ps -aq)
- docker rmi $DOCKER_IMAGE
- docker logout registry.gitlab.com
build_image:
stage: build
script:
- docker build --pull -t $DOCKER_IMAGE --build-arg USERNAME=$IMAGE_USERNAME .
- docker push $DOCKER_IMAGE
when: manual
check_version:
stage: check
script:
- docker run -di --name $CONTAINER_NAME $DOCKER_IMAGE
- docker exec $CONTAINER_NAME /bin/bash -c "ansible-playbook --version"
这还有一个额外的好处,即 Ansible 到 运行 的所有先决条件都在 build
阶段设置,并且不需要在每次 CI 进程是 运行(就像问题中的原始 gitlab-ci.yml
文件一样)。
我正在学习 Ansible
,想在我的笔记本电脑上本地使用它,目前我正在使用 "includes"。
我想准备一个剧本来导入一些其他任务(安装基础包,设置 git、vim 和 docker)并执行它。
All the code is hosted in
GitLab
and I'm using their freeCI
service to test the plays.
CI 作业将 运行 直到检查 docker
服务是否 运行ning。此时,播放将失败并显示以下消息:
fatal: [localhost]: FAILED! => {
"changed": true,
"cmd": ["service", "docker", "restart"],
"delta": "0:00:00.176233",
"end": "2017-09-28 18:49:56.194752",
"failed": true,
"msg": "non-zero return code",
"rc": 1,
"start": "2017-09-28 18:49:56.018519",
"stderr": "",
"stderr_lines": [],
"stdout": "",
"stdout_lines": []
}
我在我的笔记本电脑上创建了一个 docker 容器 (docker run --rm -ti debian
) 并在本地执行了播放,但它在同一个地方失败了。
但是,如果容器是用privileged
标志创建的,我可以手动启动服务,然后重新执行播放。这一次,它会成功完成。
所以,我的问题是:
- 如何使用
Ansible
启动docker
服务?- 我是不是完全错了,还有更好的方法来实现它吗?
- 当 运行 在我的笔记本电脑中安装容器时,我在
privilege
模式下创建了它。这允许我手动启动服务。- 因为我无法修改在
GitLab-CI
public 实例中创建容器的方式: - 在启用
privileged
标志的情况下,将我自己的 运行ner 添加到项目中可能是一个可行的解决方案吗?
- 因为我无法修改在
PS: 目前,我并不是在研究最佳实践,我只是想让这个 运行 有所作为一起玩。
环境:
- Ansible:2.4.0
- Python: 2.7.13
- Docker: 17.09.0-ce
--- --- ---
gitlab-ci.yml
文件:
image: debian:latest
variables:
HOST_INVENTORY: "./hosts"
INCLUDES_DIR: "./gists/includes"
before_script:
- apt-get update -qq
- apt-get install -y curl gcc g++ openssh-server openssh-client python python-dev python-setuptools libffi-dev libssl-dev
- easy_install pip
- pip install ansible
stages:
- syntax_check
- install
check:
stage: syntax_check
script:
- ansible-playbook -i $HOST_INVENTORY $INCLUDES_DIR/play.yml --limit 'local' --syntax-check;
run_includes:
stage: install
script:
- ANSIBLE_PIPELINING=True ansible-playbook -i $HOST_INVENTORY $INCLUDES_DIR/play.yml --limit 'local';
play.yml
很简单,只导入了一些剧本:
- hosts: local
become: yes
become_method: sudo
pre_tasks:
- import_tasks: tasks/pre.yml # update package manager cache
tasks:
- import_tasks: tasks/common.yml
- import_tasks: tasks/docker.yml
和 docker
任务:
- name: Dependencies
package:
name: "{{ item }}"
state: installed
with_items:
- apt-transport-https
- ca-certificates
- curl
- gnupg2
- software-properties-common
- name: Docker module dependencies
pip:
name: docker-py
- name: Add Docker key
shell: curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg | apt-key add -
- name: Add Docker repo
shell: echo "deb [arch=amd64] https://download.docker.com/linux/$(. /etc/os-release; echo $ID) $(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list
- name: Install Docker
apt:
pkg: docker-ce
state: installed
update_cache: yes
- name: Ensure Docker group is present
group:
name: docker
state: present
- name: Add current user to the Docker group
user:
name: "{{ ansible_user }}"
groups:
- docker
append: yes
- name: Ensure service is enabled
command: service docker restart
- name: Pull images from Docker hub
docker_image:
name: "{{ item }}"
with_items:
- debian
- cern/cc7-base
所以我在 gitlab.com
上创建了一个示例项目,其中 运行s 在 运行ner
$ echo PWD is $PWD
PWD is /builds/tarunlalwani/testci
$ id
uid=0(root) gid=0(root) groups=0(root)
$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.1 20260 2984 ? Ss 19:41 0:00 /bin/bash
root 7 0.0 0.1 20420 2652 ? S 19:41 0:00 /bin/bash
root 10 0.0 0.0 17500 1996 ? R 19:41 0:00 ps aux
$ which systemctl
/bin/systemctl
$ systemctl status docker
Failed to get D-Bus connection: Unknown error -1
ERROR: Job failed: exit code 1
如您所见,我们 运行 在一个容器中,因此您的 ansible 脚本将无法运行。没有要启动或结束的 docker 服务。此外,由于您在 docker 容器内,重新启动 docker 容器也意味着终止您正在 运行 的容器。
您需要设置一个 Ubuntu VM,然后在其上设置带有 Shell 执行程序的 Gitlab Runner。 shell 执行器意味着您在该 VM 上的命令 运行,它将具有 systemctl
和 docker
服务
另一种方法是使用 GitLab's dind
service,这样我们就可以使用已经提供的共享 运行ners 在容器内测试 playbook。
这里需要两件事:
- A
Dockerfile
在哪里构建一个基础镜像,满足 运行 Ansible 的所有要求。 - 将
gitlab-ci
文件修改为 运行 容器内的作业。
例如,Dockerfile
可能如下所示:
FROM debian:latest
ARG USERNAME
RUN apt-get update && \
apt-get install -y curl \
git \
gcc \
g++ \
libffi-dev \
libssl-dev \
openssh-client \
openssh-server \
python \
python-dev \
python-setuptools \
sudo
RUN easy_install pip && \
pip install ansible \
jmespath
RUN useradd -ms /bin/bash $USERNAME
USER $USERNAME
WORKDIR /home/$USERNAME
然后,在 gitlab-ci.yml
文件中,我们可以有如下内容:
image: docker:latest
services:
- docker:dind
variables:
DOCKER_IMAGE: "registry.gitlab.com/<YOUR_USER>/<YOUR_REPO>/dummy-image"
CONTAINER_NAME: "test"
IMAGE_USERNAME: "dummy"
stages:
- build
- check
before_script:
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.gitlab.com
after_script:
- docker rm -f $(docker ps -aq)
- docker rmi $DOCKER_IMAGE
- docker logout registry.gitlab.com
build_image:
stage: build
script:
- docker build --pull -t $DOCKER_IMAGE --build-arg USERNAME=$IMAGE_USERNAME .
- docker push $DOCKER_IMAGE
when: manual
check_version:
stage: check
script:
- docker run -di --name $CONTAINER_NAME $DOCKER_IMAGE
- docker exec $CONTAINER_NAME /bin/bash -c "ansible-playbook --version"
这还有一个额外的好处,即 Ansible 到 运行 的所有先决条件都在 build
阶段设置,并且不需要在每次 CI 进程是 运行(就像问题中的原始 gitlab-ci.yml
文件一样)。