镜像构建

## 基础镜像的选择 静态语言:越小越好 动态语言:根据情况测试 [为你的 Python 应用选择一个最好的 Docker 映像](https://aws.amazon.com/cn/blogs/china/choose-the-best-docker-image-for-your-python-application/?accessToken=eyJhbGciOiJIUzI1NiIsImtpZCI6ImRlZmF1bHQiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE2NzEyODcyNzcsImZpbGVHVUlEIjoiSlF3aGdKcmdDS1RYVEp4ViIsImlhdCI6MTY3MTI4Njk3NywiaXNzIjoidXBsb2FkZXJfYWNjZXNzX3Jlc291cmNlIiwidXNlcklkIjotNzUwMDU5MTU0Mn0.r4ouPH1QpXP8s__-Qx6-FZwvzsWGGBdrYjGb8IP0FIs) ### 动态语言的多阶段构建方法 ``` FROM python:2.7-alpine as base  RUN mkdir /svc COPY . /svc WORKDIR /svc RUN apk add --update \     postgresql-dev \     gcc \    musl-dev \     linux-headers RUN pip install wheel && pip wheel . --wheel-dir=/svc/wheels FROM python:2.7-alpine COPY --from=base /svc /svc WORKDIR /svc RUN pip install --no-index --find-links=/svc/wheels -r requirements.txt ``` ### python 构建镜像 ``` # 先导出依赖 pip freeze > requirements.txt # 编写dockerfile cat > Dockerfile <<EOF FROM python:3-slim COPY . /code WORKDIR /code RUN pip3 install --upgrade pip && \ pip3 install -r requirements.txt -i https://mirror.baidu.com/pypi/simple && \ rm -rf requirements.txt Dockerfile EXPOSE 5000 CMD ["python3", "liveness.py"] EOF docker build -t livenesspy:vi . docker run --rm -it livenesspy:vi # 较新版本的镜像docker pull python:3.9.18-bullseye docker run --rm -it -e mysql_pool="10.1.125.39:30306:root:ssqj@easyviews.pw,10.1.125.42:30306:root:ssqj@easyviews.pw," -e click_pool="10.1.125.39:31124:admin:ssqj@easyviews.pw,10.1.125.40:31124:admin:ssqj@easyviews.pw,10.1.125.42:31124:admin:ssqj@easyviews.pw," -e redis_pool="10.1.125.42:6379:qwer1234,10.1.125.41:6379:qwer1234,10.1.125.39:6379:qwer1234," -e borker_pool="10.1.125.60:9092,10.1.125.43:9092," -e interval=30 -p 5000:5000 livenesspy:vi docker tag livenesspy:vi harbor.ev.com:8000/rancher/livenesspy:v1 ``` ### go语言多阶段构建 ``` FROM golang:1.17 AS builder ENV GO111MODULE=off \ CGO_ENABLED=0 \ GOOS=linux \ GOARCH=amd64 WORKDIR /build COPY . . RUN go build -o httpserver . FROM scratch COPY --from=builder /build/httpserver / EXPOSE 8080 ENTRYPOINT ["/httpserver"] ``` ``` FROM golang:1.17 AS builder ENV GO111MODULE=off \ CGO_ENABLED=0 \ GOOS=linux \ GOARCH=amd64 \ CGO_ENABLED=0 \ GOPROXY=https://goproxy.cn,direct \ GO111MODULE=on WORKDIR /build COPY . . RUN go mod tidy && go build -o logcollect . FROM alpine COPY --from=builder /build/logcollect / COPY config/ / ENTRYPOINT ["/logcollect"] ``` ### ENTRYPOINT 和 CMD 区别 至少得定义一个(ENTRYPOINT 或者CMD),以保证运行。否则容器跑不起来容器运行时只定义它们其中一个的话,CMD和ENTRYPOINT的效果是一样的。 写法SHELL和exec,推荐exec ENTRYPOINT和CMD都可以被 docker run -- entrypoint参数 override 如果你不想开发者修改镜像缺省的执行命令,例如ping, 那么用ENTRYPOINT。  以命令(ENTRYPOINT)+ 参数(CMD)的形式,提供用户修改参数的灵活性。 如果甚至希望提供修改镜像缺省命令的能力,那么只用CMD(没有ENTRYPOINT)  这样用户可以完全地自己定义我起镜像用什么命令,灵活性最高。 测试: ``` FROM python:3-slim EXPOSE 7006 COPY procutils / ENTRYPOINT ["/procutils"] CMD ["-i", "30", "-t", "10", "-p", "7006"] ``` ``` cat Dockerfile FROM alpine ENTRYPOINT ["ping"] CMD ["www.google.com"] docker run test www.yahoo.com PING www.yahoo.com (98.139.183.24): 56 data bytes 64 bytes from 98.139.183.24: seq=0 ttl=37 time=0.590 ms root@build:~# docker run -it test sh ping: bad address 'sh' root@build:~# ``` ``` cat Dockerfile FROM alpine CMD ["ping", "www.google.com"]   docker run -it test:0.2 sh / # lsbin    dev    etc    home   lib    media  mnt    opt    proc   root   run    sbin   srv    sys    tmp    usr    var / # root@build:~# docker run test:0.2 www.baidu.com docker: Error response from daemon: failed to create shim: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "www.baidu.com": executable file not found in $PATH: unknown. ```