Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/docker/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
具有ansible等待数据库的docker_Docker_Ansible_Ansible Playbook - Fatal编程技术网

具有ansible等待数据库的docker

具有ansible等待数据库的docker,docker,ansible,ansible-playbook,Docker,Ansible,Ansible Playbook,我试着用ansible部署docker。我有一个docker数据库容器,另一个容器中是我的web应用程序,我尝试链接这两个容器。问题是数据库容器没有时间进行自我配置,而且web容器已经启动。我的ansible剧本看起来像: ... - name: run mysql in docker container docker: image: "mysql:5.5" name: database env: "MYSQL_ROOT_PASSWORD=password"

我试着用ansible部署docker。我有一个docker数据库容器,另一个容器中是我的web应用程序,我尝试链接这两个容器。问题是数据库容器没有时间进行自我配置,而且web容器已经启动。我的ansible剧本看起来像:

...
- name: run mysql in docker container
  docker:
    image: "mysql:5.5"
    name: database
    env: "MYSQL_ROOT_PASSWORD=password"
    state: running

- name: run application containers
  docker:
    name: "application"
    image: "myapp"
    ports:
      - "8080:8080"
    links:
      - "database:db"
    state: running
如何确定数据库是否已启动?我尝试了等待模块,但没有成功。我不想设置超时,这对我来说不是一个好选择。

使用模块。我不是MySQL方面的专家,但我假设在一些日志文件中会有一些端口或存在文件或消息等。您可以检查数据库是否启动

下面是从上面链接复制的
wait_for
示例

# wait 300 seconds for port 8000 to become open on the host, don't start checking for 10 seconds
- wait_for: port=8000 delay=10

# wait 300 seconds for port 8000 of any IP to close active connections, don't start checking for 10 seconds
- wait_for: host=0.0.0.0 port=8000 delay=10 state=drained

# wait 300 seconds for port 8000 of any IP to close active connections, ignoring connections for specified hosts
- wait_for: host=0.0.0.0 port=8000 state=drained exclude_hosts=10.2.1.2,10.2.1.3

# wait until the file /tmp/foo is present before continuing
- wait_for: path=/tmp/foo

# wait until the string "completed" is in the file /tmp/foo before continuing
- wait_for: path=/tmp/foo search_regex=completed

# wait until the lock file is removed
- wait_for: path=/var/lock/file.lock state=absent

# wait until the process is finished and pid was destroyed
- wait_for: path=/proc/3466/status state=absent

# wait 300 seconds for port 22 to become open and contain "OpenSSH", don't assume the inventory_hostname is resolvable
# and don't start checking for 10 seconds
- local_action: wait_for port=22 host="{{ ansible_ssh_host | default(inventory_hostname) }}" search_regex=OpenSSH delay=10

wait_for不适用于MySQL docker容器,因为它只检查端口是否可连接(对于docker容器来说这是正确的)。但是,wait_for不会检查容器内的服务是否侦听端口并向客户端发送响应

这就是我在ansible playbook中等待MySQL服务在Docker容器中完全运行的方式:

- name: Start MySQL container
  docker:
    name: some-name
    image: mysql:latest
    state: started
    ports:
    - "8306:3306" # it's important to expose the port for waiting requests
    env:
        MYSQL_ROOT_PASSWORD: "{{ mysql_root_password }}"

- template: mode="a+rx,o=rwx" src=telnet.sh.j2 dest=/home/ubuntu/telnet.sh

# wait while MySQL is starting
- action: shell /home/ubuntu/telnet.sh
  register: result
  until: result.stdout.find("mysql_native_password") != -1
  retries: 10
  delay: 3
telnet.sh.j2是

#!/bin/bash -e

telnet localhost 8306 || true

为了避免sh和我通常没有安装telnet

- name: Wait for database to be available
  shell: docker run --rm --link mysql:mysql mysql sh -c 'mysql -h"$MYSQL_PORT_3306_TCP_ADDR" -P"$MYSQL_PORT_3306_TCP_PORT" -uroot -p{{mysql_password}} || true'
  register: result
  until: result.stderr.find("Can't connect to MySQL") == -1
  retries: 10
  delay: 3

这对我来说很好:

  - name: get mariadb IP address
    command: "docker inspect --format '{''{ .NetworkSettings.IPAddress }''}' mariadb-container"
    register: mariadb_ip_address
  - name: wait for mariadb to become ready
    wait_for:
      host: "{{ mariadb_ip_address.stdout }}"
      port: 3306
      state: started
      delay: 5
      connect_timeout: 15
      timeout: 30
作为:

wait_for不适用于MySQL docker容器,因为它只检查端口是否可连接(直接适用于docker容器)。但是,wait_for不会检查容器内的服务是否侦听端口并向客户端发送响应

使用,无需shell脚本或telnet即可等待:

- name: Wait for mariadb
  command: >
    docker exec {{ container|quote }}
    mysqladmin ping -u{{ superuser|quote }} -p{{ superuser_password|quote }}
  register: result
  until: not result.rc  # or result.rc == 0 if you prefer
  retries: 20
  delay: 3

这将运行
mysqladmin ping…
,直到成功(返回代码0)。通常超级用户是
root
。我使用podman而不是docker进行了测试,但我相信不管怎样,命令都是一样的
| quote
是否执行shell转义,在使用
命令时也应执行此操作:

,而我也认为
等待
成为正确答案这会导致另一个问题:如何计算docker容器的IP地址?数据库容器没有绑定到本地主机上的端口,因此要等待它启动,我们需要docker为容器分配的IP地址。我目前正在使用
docker inspect
获取IP,但这还没有提供结果。@Tobias可能会发布一个带有适当详细信息的新问题。您为什么要在单独的脚本中运行telnet命令?这对我很有效,我喜欢它避免使用脚本或telnet。我使用的变体是
mysqladmin ping
docker exec
。我使用
命令
模块和
docker exec{{container_name}}mysqladmin ping
,然后使用
,直到
变成
result.rc==0
。是否有一个版本不需要根MySQL用户?@JeroenDeDauw我不确定是否尝试与普通用户一起运行它,它可能会正常工作。如果没有,您可以尝试调用
SELECT 1mysql