Docker -- 记录一下我在web项目中通过python+dockerfile一键创建或删除镜像和容器的脚本

52 阅读4分钟

前言

  • 首先说明一下这个脚本的用意
  • 我在项目中为不同的环境写了两份dockerfile,用于将web工程的打包文件,本地部署到docker容器中,为的是有时候需要模拟出线上部署效果
  • 然后为了图个省事,不用每次都来回删除创建容器和镜像,写下了这个python脚本

此 python 脚本效果截图

  • python 脚本中会到用的文件截图

dockerfile

nginx.conf

  • python 脚本终端效果截图

dockerWX20231222-134025@2x.png

代码在此!!!

  • build-dockerfile.py
import os,socket

def string_to_num(s):
    try:
        return int(s)
    except Exception:
        return 0

def get_sys_type():
    if os.name == 'nt':
        # windows
        return 'win'
    if os.name == 'posix':
        # mac
        return 'mac'

# 获取 mac 系统的 ip4
def get_mac_host_ip4():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.connect(("8.8.8.8", 80))  
    ip_address = s.getsockname()[0]
    s.close()
    return ip_address

# 获取 windows 系统的 ip4
def get_win_host_ip4():
    ip_address = socket.gethostbyname(socket.getfqdn())
    return ip_address

def get_host_ip4():
    # 判定当前是 Mac 系统还是 Windows 系统
    sys_type = get_sys_type()
    if sys_type == 'mac':
        # Mac
        return get_mac_host_ip4()
    elif sys_type == 'win':
        # Windows
        return get_win_host_ip4()
    return 'unknown-system'


# 对应要执行的 dockerfile 脚本文件
env_dockerfiles = [
    "dockerfile.dev",
    "dockerfile.prod"
]

# 对应要创建的镜像名称
env_dockerimages = [
    "nginximage:dev",
    "nginximage:prod"
]

# 对应要创建的容器名称
env_dockercontainers = [
    "nginx_container_dev",
    "nginx_container_prod"
]

# 对应容器映射到宿主机的端口号
env_dockercontainers_ports = [
    "8180",
    "8181"
]

# 环境选项
env_options = [
    "1.开发环境 - dockerfile:{} - dockerImage:{} - dockerContainer:{} - port:{}".format(env_dockerfiles[0], env_dockerimages[0], env_dockercontainers[0], env_dockercontainers_ports[0]),
    "2.生产环境 - dockerfile:{} - dockerImage:{} - dockerContainer:{} - port:{}".format(env_dockerfiles[1], env_dockerimages[1], env_dockercontainers[1], env_dockercontainers_ports[1]),
]

def get_env_selection(ins):
    in_num = string_to_num(ins) - 1
    if in_num < 0:
        in_num = 0
    elif in_num > 1:
        in_num = 1
    return env_options[in_num],in_num

def ask_create_info():
    # 提示选择环境类型
    print("即将为你创建docker容器")
    
    print("----------- 选择环境类型 ---------------")
    # 遍历循环输出提示
    for i in env_options:
        print(i)
    in_num = input("请输入环境类型(1/2/3):")
    print("-------------------------------------")
    selection,env_num = get_env_selection(in_num)
    print("你选择的环境是:{}".format(selection))

    return env_num

def execute_dockerfile(env_num, action_type):
    # 执行 dockerfile 脚本
    dockerfile_name = env_dockerfiles[env_num]
    docker_image = env_dockerimages[env_num]
    docker_container = env_dockercontainers[env_num]
    docker_container_port = env_dockercontainers_ports[env_num]

    rm_docker_container_cmd = "docker rm -f {}".format(docker_container)
    rm_docker_image_cmd = "docker rmi {}".format(docker_image)
    build_image_cmd = "docker build -t {} -f {} .".format(docker_image, dockerfile_name)
    run_docker_container_cmd = "docker run -d --name {} -p {}:80 {}".format(docker_container, docker_container_port, docker_image)
    
    print("----------- 正在执行 docker 脚本... ---------------")
    print("正在 移除 容器...")
    print(rm_docker_container_cmd)
    os.system(rm_docker_container_cmd)
    print("正在 移除 镜像...")
    print(rm_docker_image_cmd)
    os.system(rm_docker_image_cmd)
    if action_type == "create":
        print("正在 创建 镜像...")
        print(build_image_cmd)
        os.system(build_image_cmd)
        print("正在 创建 容器...")
        print(run_docker_container_cmd)
        os.system(run_docker_container_cmd)
        print("**************************")
        print("容器部署网站访问地址:")
        print("http://localhost:{}".format(docker_container_port))
        print("http://{}:{}".format(get_host_ip4(), docker_container_port))
        print("**************************")
    print("-------------------------------------")
    print("执行完毕")
    print("-------------------------------------")

action_options = ["1. 创建容器和镜像","2. 删除容器和镜像"]
def get_action_selection(ins):
    in_num = string_to_num(ins) - 1
    if in_num < 0:
        in_num = 0
    elif in_num > 1:
        in_num = 1
    return action_options[in_num], in_num

def ask_action():
    # 提示选择操作类型
    print("----------- 选择操作类型 ---------------")
    # 遍历循环输出提示
    for i in action_options:
        print(i)
    print("-------------------------------------")
    in_num = input("请输入操作类型(1/2):")
    print("-------------------------------------")
    selection, action_num = get_action_selection(in_num)
    print("你选择的操作是:{}".format(selection))
    return action_num

# 主入口:
if __name__ == "__main__":
    act_num = ask_action()
    if act_num == 0:
        env_num = ask_create_info()
        execute_dockerfile(env_num, 'create')
    elif act_num == 1:
        env_num = ask_create_info()
        execute_dockerfile(env_num, 'remove')
  • dockerfile.dev
FROM nginx

# 拷贝web应用目录到容器目录
COPY /unpackage/dist/build/h5 /usr/share/nginx/html

# 拷贝自定义配置文件
COPY nginx-dev.conf /etc/nginx/conf.d/default.conf

# 暴露端口
EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

# 请在项目的根目录下执行以下的 dockerfile 构建指令
# 创建镜像和容器命令行记录(命令说明:-f dockerfile 指定Dockerfile文件名; . 代表当前目录)
# docker build -t nginximage:dev -f dockerfile.dev .
# docker run -d --name nginx_container_dev -p 8180:80 nginximage:dev

# 以交互方式运行容器,即终端会进入容器,终端退出则容器也会移除(临时容器)
# docker run -it --rm --name my-running-app -p 8180:80 nginximage:dev

# 移除容器
# docker rm -f nginx_container_dev

# 移除镜像
# docker rmi nginximage:dev
  • nginx-dev.conf
server {
    listen 80;
    server_name localhost;

    location /devapi/ {
        rewrite /devapi/(.*) /$1 break;
        proxy_pass https://zjavim.qj-chg.com:9998;
        proxy_set_header Host $host;
        proxy_method $request_method;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;

        if ($request_uri ~ ^/devapi/) { 
            break;
        }
    }
}
  • dockerfile.prod 同 dockerfile.dev
  • nginx-prod.conf 同 nginx-dev.conf