| """ |
| Python 版镜像构建脚本: |
| 1. 写 requirements.txt / Dockerfile |
| 2. docker build |
| 3. (可选) docker push |
| """ |
|
|
| import argparse |
| import subprocess |
| from pathlib import Path |
| import textwrap |
| import sys |
|
|
| DEFAULT_REQS = """\ |
| pandas==2.2.2 |
| numpy==1.26.4 |
| sqlalchemy>=2.0,<3.0 |
| |
| |
| |
| |
| """ |
|
|
| DOCKERFILE_TMPL = """\ |
| FROM python:{py_version}-slim AS runtime |
| RUN apt-get update && apt-get install -y --no-install-recommends \\ |
| build-essential gcc \\ |
| && rm -rf /var/lib/apt/lists/* |
| COPY requirements.txt /tmp/requirements.txt |
| RUN python -m pip install --no-cache-dir -r /tmp/requirements.txt |
| RUN useradd -ms /bin/bash appuser |
| USER appuser |
| WORKDIR /app |
| ENTRYPOINT ["python"] |
| """ |
|
|
| def run(cmd: list[str], **kw): |
| print(">>", " ".join(cmd)) |
| subprocess.run(cmd, check=True, **kw) |
|
|
| def main(): |
| parser = argparse.ArgumentParser() |
| parser.add_argument("-i", "--image", default="myorg/dataflow-py:3.11", |
| help="镜像名:TAG") |
| parser.add_argument("--py", "--python", dest="py_version", |
| default="3.11", help="Python 主版本") |
| parser.add_argument("--push", action="store_true", |
| help="构建后 docker push") |
| opts = parser.parse_args() |
|
|
| root = Path(__file__).resolve().parent |
| docker_dir = root / "docker" |
| docker_dir.mkdir(exist_ok=True) |
|
|
| |
| (docker_dir / "requirements.txt").write_text(DEFAULT_REQS, encoding="utf-8") |
| print("✓ requirements.txt written") |
|
|
| |
| dockerfile_str = DOCKERFILE_TMPL.format(py_version=opts.py_version) |
| (docker_dir / "Dockerfile").write_text(dockerfile_str, encoding="utf-8") |
| print("✓ Dockerfile written") |
|
|
| |
| run(["docker", "build", "-t", opts.image, str(docker_dir)]) |
|
|
| |
| if opts.push: |
| run(["docker", "push", opts.image]) |
|
|
| print(f"\n 完成!请把 DOCKER_IMAGE 改为 '{opts.image}'\n") |
|
|
| if __name__ == "__main__": |
| try: |
| main() |
| except subprocess.CalledProcessError as e: |
| sys.exit(e.returncode) |