一些使用docker的tips

·

2 min read

作为docker重度使用者,有时也会犯一些低级错误,记录一下长期使用下来的一些经验,长期更新

ADD or COPY

不只一位同事问过我这个问题:在Dockerfile里面看到了下面这一句,但是进入容器之后,在/tmp目录并没有发现buildkit-v0.12.3.darwin-amd64.tar.gz,只看到了解压后的`bin`文件夹,为何没看到解压呢?

ADD buildkit-v0.12.3.darwin-amd64.tar.gz /tmp
# ls /tmp
# bin

这是因为在Dockerfile里面,ADD不仅有COPY字面上的意义,还可以

  • 下载网络资源

  • 解压文件

不要需要注意的,下载和解压这两件事是或的关系,也就是说

ADD https://xxx.tar.gz .

RUN curl -O https://xxx.tar.gz

的效果是一致的。(ps: 千万不要期望`ADD xxx.tar.gz .` 既能下载又帮你解压)

COPY/ADD文件/文件夹

当你想要在Dockerfile上COPY文件夹的时候

FROM busybox:1.35.0-glibc
COPY bin /tmp
# ls /tmp
# buildctl

但其它我想要复制的整个文件夹,而不仅仅是将文件夹里面的内容复制到/tmp文件夹下,

FROM busybox:1.35.0-glibc
COPY bin /tmp/bin
# ls /tmp
# bin

之前踩到这个坑,因为会不自觉地把COPY当`mv`命令来用

heredocs

我是在推上看到这个的,果然要与时俱进哇

RUN apt-get update -y \
    && apt-get install -y --no-install-recommends curl libsasl2-2 gsasl libnss-ldapd libssl-dev netcat-traditional procps krb5-user locales \
    && rm -rf  /var/lib/apt/lists/*

虽然我不是一个强迫症患者,但我也是爱整洁的,所以更喜欢下面这种写法

RUN <<EOF
apt-get update -y 
apt-get install -y --no-install-recommends curl libsasl2-2 gsasl libnss-ldapd libssl-dev netcat-traditional procps krb5-user locales 
rm -rf  /var/lib/apt/lists/*
EOF

值得注意的是,因为你使用`docker buildx build`而不是docker build, 则需要在Dockerfile的第一行加上以下语句:

# syntax=docker/dockerfile:1

ARG

将ARG赋值给ENV

就在前两天我被自己坑了

ARG MY_ARG
FROM busybox:1.35.0-glibc
ENV MY_ENV=$MY_ARG

`docker build --build-arg MY_ARG=test -t argtest .`

docker run --rm -it argtest env |grep MY_ENV                
MY_ENV=

我第一反应是:竟然是空的,这不对呀,就很奇怪

FROM busybox:1.35.0-glibc
ARG MY_ARG
ENV MY_ENV=$MY_ARG

原来需要调整下ARG的位置

docker run --rm -it argtest env |grep MY_ENV                
MY_ENV=test

只是,没有找到为何这样做以及出处

多阶段构建传递ARG

ARG MY_ARG
FROM busybox:1.35.0-glibc

FROM alpine:3.18
ENV MY_ENV=$MY_ARG

没有意外,MY_ENV是空的

若要将MY_ARG传到alpine:3.18那一层,显示声明MY_ARG即可

ARG MY_ARG
FROM busybox:1.35.0-glibc

FROM alpine:3.18
ARG MY_ARG
ENV MY_ENV=$MY_ARG

多架构镜像的构建

其实,若不是要支持所谓的“信创”,平时工作中也没机会构建ARM镜像的,但既然有这个机会,借此契机,自然也折腾了一番,除了docker官网,我主要参考了这篇文章Multi-Architecture Docker Images

唯一需要补充的是关于配置方面,如果你使用的是一个私有的harbor镜像仓库(eg: 私有镜像仓库是:172.16.2.130),需要在buildkit的配置文件中添加以下配置

# /etc/buildkitd.toml
debug = true
[registry."172.16.2.130"]
  http = true
  insecure = true

还是来上一个实际的使用案例吧

FROM busybox:1.35.0-glibc
CMD ["uname", "-i"]

构建amd64和arm64镜像,并推送到私有harbor镜像仓库

docker buildx build --platform linux/amd64,linux/arm64 \
    -t 172.16.2.130/capops/multiarch:v0.0.1 . --push

使用这种方法的好处的: 同一份Dockerfile,构建出来的不同架构的镜像,共用同一个镜像tag,例如以上命令,在amd64的机器上执行docker pull 172.16.2.130/capops/multiarch:v0.0.1 获取的是amd64格式的镜像,如下所示

$ docker inspect --format='{{.Os}}/{{.Architecture}}' 172.16.2.130/capops/multiarch:v0.0.1
linux/amd64

而在arm64的机器上执行docker pull 172.16.2.130/capops/multiarch:v0.0.1 获取的是arm64格式的镜像,应用层无需要做任何变动。

参考: