如何在容器执行的脚本调用 exit() 后退出“docker run”容器

问题描述 投票:0回答:2

我有一个 docker-compose 设置,它分三步部署:

  1. 构建所有容器和
    dc up -d
    dc
    docker-compose
    的别名)
  2. 创建数据库:
    dc run web /usr/local/bin/python create_db.py
  3. 填充数据库:
    dc run -d web /usr/local/bin/python -u manage.py populateDB

第 2 步和第 3 步创建新容器(参见前两个):

~/Documents/Project » docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                              PORTS                    NAMES
2ead532ea58b        myproject_web       "/usr/local/bin/pytho"   8 minutes ago       Up 8 minutes                        8000/tcp                 myproject_web_run_2
64e1f81ecd1a        myproject_web       "/usr/local/bin/pytho"   9 minutes ago       Restarting (0) About a minute ago   8000/tcp                 myproject_web_run_1
9f5c670d4d7f        myproject_nginx     "/usr/sbin/nginx"        40 minutes ago      Up 40 minutes                       0.0.0.0:80->80/tcp       myproject_nginx_1
46d3e8c09c03        myproject_web       "/usr/local/bin/gunic"   40 minutes ago      Up 40 minutes                       8000/tcp                 myproject_web_1
ea876e68c8c6        postgres:latest     "/docker-entrypoint.s"   40 minutes ago      Up 40 minutes                       0.0.0.0:5432->5432/tcp   myproject_postgres_1

这一切都很好,除了他们在他们的工作完成后不退出

例如,create db 脚本,如您所见,它总是在创建数据库后重新启动。一旦

achromap_web_run_2
完成填充数据库,它将添加每条记录的第二个副本,然后是第三个,等等。永远。

在 github 上,这似乎是 docker 要求的,

docker run --rm
标志处理它。但是
--rm
-d
不相容,我不明白。

你知道如何杀死已经完成其功能的容器吗?具体来说,一旦create_db.py调用

dc run web /usr/local/bin/python create_db.py
,如何让
exit()
退出?或者有更好的方法吗?

docker docker-compose
2个回答
1
投票

我想你可能把两件事混为一谈了。

--rm 标志

它的存在是为了在容器完成后进行清理,因此它不会在死容器池中徘徊。正如您已经发现的那样,它与

-d
不兼容。但在这种情况下,你根本不需要它。

--重启标志

(也可在 docker-compose 中用作

restart
属性。)

此标志设置重启策略。默认情况下,它设置为

no
,但您可以将其设置为其他一些值,包括
always
。我怀疑你目前将它设置为
always
,这将强制容器在每次自行停止时重新启动。

如果您手动停止容器 (

docker stop ...
),那么自动重启将不会启动。但是如果进程自己退出,或者崩溃了,那么容器会被重启。这是可用的,原因很明显,因此如果它崩溃,您的服务将重新启动。

如何进行

我会说你需要的是使用

exec
而不是
run
来完成这些任务。

首先,正常运行您的容器(即

docker-compose up -d
)。

而不是使用

run
来执行
create_db.py
,使用
exec

docker-compose exec web /usr/local/bin/python create_db.py

这将使用您已经运行的容器,执行一次脚本,当脚本退出时,您就完成了。由于您没有创建新容器(就像

run
所做的那样),因此之后没有清理工作。

请注意,您不需要经常与

-it
一起使用的
docker exec
标志。 docker-compose 默认情况下在
exec
上模拟 tty。


0
投票

我创建了一个 Python 脚本来停止所有 docker 容器,并在其中一个容器退出时将其删除。至于 docker compose 文件,一旦容器退出,就没有停止容器的标志。您可以按照自己喜欢的方式修改它,例如,除了 docker-compose 之外,您还可以在函数“start_docker_services”和“docker_services_watcher”中使用 docker run 命令。

import os, time, multiprocessing


# Process class
class Process(multiprocessing.Process):
    def __init__(self, id):
        super(Process, self).__init__()
        self.id = id
  
    def run(self):

        if self.id == 0:
            start_docker_services()
        
        if self.id == 1:
            docker_services_watcher()


def start_docker_services():
    os.system("docker compose up --build")


def docker_services_watcher():

    print("\ndocker services watcher will start in 10 seonds.")
    time.sleep(10)

    # all containers (reading how many containers are running)
    mydata = os.popen("docker compose ps").read()
    # print("\n", mydata)

    keep_running = True
    
    # as every service run on a port so we are counting the string tcp 
    total_services_in_start = mydata.count("/tcp")

    while keep_running:

        current_total_services = os.popen("docker compose ps").read().count("/tcp")

        if current_total_services == total_services_in_start:
            print(
                f"all services are running, total services: \
                {current_total_services} / {total_services_in_start}"
            )
            time.sleep(5) # after every 5 seconds will check again
        else:
            print("one of the service stopped, closing docker containers...")
            keep_running = False

    os.system("docker compose down")


if __name__ == '__main__':


    p = Process(0)
    p.start()

    p = Process(1)
    p.start()
    p.join()
© www.soinside.com 2019 - 2024. All rights reserved.