镜像构建
## 基础镜像的选择
静态语言:越小越好
动态语言:根据情况测试
[为你的 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.
```