20-docker 容器dockerfile命令详解
1.docker命令详解
# 设置以哪个镜像为基础
FROM ubuntu
# 维护者信息
MAINTAINER Example McAuthor
# 每RUN就新建立一层,如执行commit 这一层的修改,构成新的镜像, 42 层,现在是不得超过 127 层
RUN yum install wget \
&& curl \
&& lrzsz \
&& nmap
# COPY 指令将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。
# 使用 COPY 指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等。
# 目标路径不需要事先创建,如果目录不存在会在复制文件前先行创建缺失目录
COPY package.json /usr/src/app/
# 如果是文件,那下载后的文件权限自动设置为 600
# 复制文件进去,就不能用ADD,自动解压缩的场合就用ADD
# ADD 指令会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢
ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz /
# CMD一定要使用双引号 ",而不要使用单引号
CMD ["nginx", "-g", "daemon off;"]
# ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数
# 需要在镜像后面再执行命令时用ENTRYPOINT
FROM ubuntu:16.04
RUN apt-get update \
&& apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*
ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]
# 场景一:让镜像变成像命令一样使用
$ docker run myip
当前 IP:61.148.226.66 来自:北京市 联通
$ docker run myip -i
HTTP/1.1 200 OK
Server: nginx/1.8.0
# 场景二:应用运行前的准备工作
FROM alpine:3.4
...
RUN addgroup -S redis && adduser -S -G redis redis
...
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 6379
CMD [ "redis-server" ]
#!/bin/sh
...
# allow the container to be started with `--user`
if [ "$1" = 'redis-server' -a "$(id -u)" = '0' ]; then
chown -R redis .
exec su-exec redis "$0" "$@"
fi
exec "$@"
该脚本的内容就是根据 CMD 的内容来判断,如果是 redis-server 的话,则切换到 redis 用户身份启动服务器,否则依旧使用 root 身份执行。比如:
$ docker run -it redis id
uid=0(root) gid=0(root) groups=0(root)
# ENV 设置环境变量
ENV NODE_VERSION 7.2.0
RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
&& curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \
&& gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
&& grep " node-v$NODE_VERSION-linux-x64.tar.xz\$" SHASUMS256.txt | sha256sum -c - \
&& tar -xJf "node-v$NODE_VERSION-linux-x64.tar.xz" -C /usr/local --strip-components=1 \
&& rm "node-v$NODE_VERSION-linux-x64.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \
&& ln -s /usr/local/bin/node /usr/local/bin/nodejs
# VOLUME 定义匿名卷
VOLUME /data
# EXPOSE 声明端口
EXPOSE 80/tcp
EXPOSE 80/udp
EXPOSE 3306
# WORKDIR 指定工作目录,如该目录不存在,WORKDIR 会帮你建立目录
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
# USER 指定当前用户
RUN groupadd -r redis && useradd -r -g redis redis
USER redis
RUN [ "redis-server" ]
如果以 root 执行的脚本,在执行期间希望改变身份,比如希望以某个已经建立好的用户来运行某个服务进程,不要使用 su 或者 sudo,这些都需要比较麻烦的配置,而且在 TTY 缺失的环境下经常出错。建议使用 gosu。
# 建立 redis 用户,并使用 gosu 换另一个用户执行命令
RUN groupadd -r redis && useradd -r -g redis redis
# 下载 gosu
RUN wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.7/gosu-amd64" \
&& chmod +x /usr/local/bin/gosu \
&& gosu nobody true
# 设置 CMD,并以另外的用户执行
CMD [ "exec", "gosu", "redis", "redis-server" ]
# HEALTHCHECK 健康检查
FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s \
CMD curl -fs http://localhost/ || exit 1
#
这次我们回到原始的 Dockerfile,但是这次将项目相关的指令加上 ONBUILD,这样在构建基础镜像的时候,这三行并不会被执行。然后各个项目的 Dockerfile 就变成了简单地:
FROM node:slim
RUN mkdir /app
WORKDIR /app
ONBUILD COPY ./package.json /app
ONBUILD RUN [ "npm", "install" ]
ONBUILD COPY . /app/
CMD [ "npm", "start" ]
# 只有这么一行。当在各个项目目录中,用这个只有一行的 Dockerfile 构建镜像时,之前基础镜像的那三行 ONBUILD 就会开始执行,成功的将当前项目的代码复制进镜像、并且针对本项目执行 npm install,生成应用镜像。
FROM my-node

浙公网安备 33010602011771号