【问题标题】:Does docker-compose support init container?docker-compose 是否支持初始化容器?
【发布时间】:2022-01-16 04:19:26
【问题描述】:

init container 是 Kubernetes 的一个很棒的功能,我想知道 docker-compose 是否支持它?它允许我在启动主应用程序之前运行一些命令。

我遇到了这个 PR https://github.com/docker/compose-cli/issues/1499,它提到支持初始化容器。但我在他们的参考资料中找不到相关文档。

【问题讨论】:

    标签: docker docker-compose


    【解决方案1】:

    这对我来说是一个发现,但是是的,现在可以使用带有 docker-compose 的 init 容器,因为版本 1.29 可以在您在问题中链接的 PR 中看到。

    同时,当我写这些行时,似乎this feature has not yet found its way to the documentation

    您可以定义对另一个容器的依赖,条件基本上是“当另一个容器成功完成其工作时”。这为定义运行任何类型脚本的容器留下了空间,并在启动其他依赖容器之前完成它们并退出。

    为了说明,我用一个非常常见的场景制作了一个示例:启动 db 容器,确保 db 已启动并在启动应用程序容器之前初始化其数据。

    注意:初始化 db(至少就官方 mysql 映像而言)不需要 init 容器,因此此示例与其说是坚如磐石的典型工作流程,不如说是一个说明。

    complete example is available in a public github repo 所以我只会在这个答案中显示关键点。

    让我们从撰写文件开始

    ---
    x-common-env: &cenv
        MYSQL_ROOT_PASSWORD: totopipobingo
    
    services:
        db:
            image: mysql:8.0
            command: --default-authentication-plugin=mysql_native_password
            environment:
                <<: *cenv
        init-db:
            image: mysql:8.0
            command: /initproject.sh
            environment:
                <<: *cenv
            volumes:
                - ./initproject.sh:/initproject.sh
            depends_on:
                db:
                    condition: service_started
        my_app:
            build:
                context: ./php
            environment:
                <<: *cenv
            volumes:
                - ./index.php:/var/www/html/index.php
            ports:
                - 9999:80
            depends_on:
                init-db:
                    condition: service_completed_successfully
    

    你可以看到我定义了 3 个服务:

    • 最先启动的数据库
    • 仅在 db 启动后启动的 init 容器。这个只运行一个脚本(见下文),一旦一切都被初始化就会退出
    • 只有在 init 容器成功完成其工作后才会启动的应用程序容器。

    db-init 容器运行的initproject.sh 脚​​本对于这个演示来说是非常基本的,它只是每 2 秒重试一次连接到数据库,直到它成功或达到 50 次尝试的限制,然后创建一个数据库/表和插入一些数据:

    #! /usr/bin/env bash
    
    # Test we can access the db container allowing for start
    for i in {1..50}; do mysql -u root -p${MYSQL_ROOT_PASSWORD} -h db -e "show databases" && s=0 && break || s=$? && sleep 2; done
    if [ ! $s -eq 0 ]; then exit $s; fi
    
    # Init some stuff in db before leaving the floor to the application
    mysql -u root -p${MYSQL_ROOT_PASSWORD} -h db -e "create database my_app"
    mysql -u root -p${MYSQL_ROOT_PASSWORD} -h db -e "create table my_app.test (id int unsigned not null auto_increment primary key, myval varchar(255) not null)"
    mysql -u root -p${MYSQL_ROOT_PASSWORD} -h db -e "insert into my_app.test (myval) values ('toto'), ('pipo'), ('bingo')"
    

    应用程序容器的 Dockerfile 很简单(为 php 添加 mysqli 驱动程序),可以在 example repo 中找到,以及通过在浏览器中调用 http://localhost:9999 来测试初始化​​是否成功的 php 脚本。

    有趣的部分是观察使用docker-compose up -d启动服务时发生了什么。

    使用此类功能可以完成的唯一限制可能是您的想象力;)感谢您让我发现这一点。

    【讨论】:

    • 很好的答案。允许我绕过github.com/docker/compose/issues/3140 中描述的限制,现在我有一个可靠的解决方案来等待 Postgres DB 准备好,然后再生成依赖它的容器。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多