1. Dockerfile 指令
FROM: 指定基础镜像
服务类镜像: nginx
、redis
、mongo
、mysql
、httpd
、php
、tomcat
语言类镜像: node
、openjdk
、python
、ruby
、golang
操作系统镜像: ubuntu
、debian
、centos
、fedora
、alpine
空白镜像:scratch
适用于静态编译的程序,不需要操作系统支撑。
COPY: 复制文件
ADD: 支持添加URL,自动解压文件等
WORKDIR: 指定默认目录工作
RUN: 构建镜像时执行, 用于安装应用和软件包,创建用户等操作
CMD: 运行容器的启动命令,可被替换
ENTRYPOINT: 同CMD, 但支持额外参数
ENV: 设置环境变量
VOLUME: 定义匿名卷
EXPOSE: 曝露端口
USER:指定当前用户
HEALTHCHECK
2. 使用scratch镜像 2.1 直接使用编译好的C程序 (依赖外部库,直接报错) 1 2 3 4 5 #include <stdio.h> void main () { printf ("hello world\n" ); }
1 2 3 4 FROM scratchCOPY hello / CMD ["/hello" ]
1 2 3 4 5 6 gcc hello.c -o hello docker build -t hello . docker run --rm hello standard_init_linux.go:190: exec user process caused "no such file or directory"
2.2 改用golang程序 1 2 3 4 5 6 7 package mainimport "fmt" func main () { fmt.Println("hello world" ) }
1 2 3 4 5 6 7 8 FROM golang as builderWORKDIR /go/src/app COPY hello.go . RUN go build -ldflags="-w -s" hello.go FROM scratchCOPY --from=builder /go/src/app/hello / CMD ["/hello" ]
1 2 docker build -t hello . docker run --rm hello
2.3 不使用标准库的C版本 1 2 3 4 5 6 7 8 9 10 11 12 13 #include <sys/syscall.h> #ifndef DOCKER_GREETING #define DOCKER_GREETING "Hello from Docker" #endif const char message[] = DOCKER_GREETING "\n" ;void _start() { syscall(SYS_write, 1 , message, sizeof (message)-1 ); syscall(SYS_exit, 0 ); }
1 2 3 4 FROM scratchCOPY hello / CMD ["/hello" ]
1 2 3 4 5 gcc -static -Os -nostartfiles -fno-asynchronous-unwind-tables -o hello hello.c docker build -t hello . docker run --rm hello
3. 错误的文件系统操作 在 Shell 中,连续两行是同一个进程执行环境,因此前一个命令修改的内存状态,会直接影响后一个命令;而在 Dockerfile 中,这两行 RUN 命令的执行环境根本不同,是两个完全不同的容器。这就是对 Dockerfile 构建分层存储的概念不了解所导致的错误。
1 2 RUN cd /app RUN echo "hello" > world.txt
4. RUN & CMD & ENTRYPOINT 4.1 docker中的进程,必须以前台方式启动 对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出,其它辅助进程不是它需要关心的东西。
1 2 3 4 5 6 7 8 9 CMD echo $HOME CMD ["sh" , "-c" , "echo $HOME " ] CMD service nginx start CMD ["sh" , "-c" , "service nginx start" ] CMD ["nginx" , "-g" , "daemon off" ]
4.2 支持额外参数 1 2 3 4 5 6 7 8 FROM ubuntuRUN apt-get update \ && apt-get install -y curl \ && rm -rf /var/lob/apt/lists/* ENTRYPOINT ["curl" , "-s" , "https://cip.cc" ]
1 2 3 4 docker build -t myip . docker run --rm myip docker run --rm myip -i
4.3 应用运行前的准备工作 某些应用,需要在运行主进程钱,做一些准备工作。mysql需要提前进行数据库配置、初始化工作
1 2 3 4 5 6 7 8 9 FROM alpine:3.4 ... RUN addgroup -S redis && adduser -S -G redis redis ... ENTRYPOINT ["docker-entrypoint.sh" ] USER redis EXPOSE 6379 CMD [ "redis-server" ]
1 2 3 4 5 6 7 8 9 #!/bin/sh ... if [ "$1 " = 'redis-server' -a "$(id -u) " = '0' ]; then chown -R redis . exec su-exec redis "$0 " "$@ " fi exec "$@ "
1 2 3 4 5 docker run -it redis id docker run --name redis-srv -d redis
5. 其他示例 5.1 命令细节说明 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 FROM busyboxMAINTAINER "eli.he@live.cn" ENV WEB_ROOT="/data/www/html/" WORKDIR ${WEB_ROOT} COPY index.html . COPY app ./app ADD http://nginx.org/download/nginx-1.19.2.tar.gz /usr/local /src/ ADD nginx-1.19.2.tar.gz /usr/local /src/ VOLUME /data/www/mysql EXPOSE 80 /tcp 443 /tcp RUN cd /usr/local /src/ && tar xf nginx-1.19.2.tar.gz CMD /bin/httpd -f -h $WEB_ROOT CMD ["/bin/httpd" , "-f" , "-h $WEB_ROOT " ] CMD ["/bin/sh" , "-c" , "/bin/httpd" , "-f" , "-h $WEB_ROOT " ] ENTRYPOINT /bin/httpd -f -h $WEB_ROOT CMD ["/bin/httpd" , "-f" , "-h $WEB_ROOT " ] ENTRYPOINT ["/bin/sh" , "-c" ] HEALTHCHECK --interval=5m --timeout=3s \ CMD curl -f http://localhost/ || exit 1
5.2 自定义nginx镜像 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 FROM nginx:1.19 .2 -alpineLABEL maintainer="eli.he@live.cn" ENV WEB_ROOT="/data/www/html/" WORKDIR $WEB_ROOT ADD index.html ./ ADD entrypoint.sh /bin/ RUN chmod +x /bin/entrypoint.sh EXPOSE 80 /tcpHEALTHCHECK --start-period=3s CMD curl -o - -q http://${IP:-0.0.0.0} :${PORT:-80} CMD ["/usr/sbin/nginx" , "-g" , "daemon off;" ] ENTRYPOINT ["/bin/entrypoint.sh" ]
1 2 3 4 5 6 7 8 9 10 11 12 #!/bin/sh cat > /etc/nginx/conf.d/http.conf <<EOF server { server_name $HOSTNAME; listen ${IP:-0.0.0.0}:${PORT:-80}; root ${WEB_ROOT:-/usr/share/nginx/html}; } EOF exec "$@ "
1 2 3 docker build -t myweb:v0.1 . docker run --name web1 -P -d myweb:v0.1