2, docker-镜像使用

Docker 运行容器前需要本地存在对应的镜像,如果本地不存在该镜像,Docker 会从镜像仓库下载该镜像。

获取镜像

Docker Hub 上有大量的高质量的镜像可以用,从 Docker 镜像仓库获取镜像的命令是 docker pull。其命令格式为:

docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]

镜像名称的格式:

  • Docker 镜像仓库地址:地址的格式一般是 <域名/IP>[:端口号]。默认地址是 Docker Hub。
  • 仓库名:如之前所说,这里的仓库名是两段式名称,即 <用户名>/<软件名>。对于 Docker Hub,如果不给出用户名,则默认为 library,也就是官方镜像。

比如:

docker pull ubuntu:18.04

运行镜像

使用docker run命令来以镜像为基础启动并运行一个容器。

 docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
docker run -it --rm  ubuntu:18.04  bash
  • -it:这是两个参数,一个是 -i:交互式操作,一个是 -t 终端。我们这里打算进入 bash 执行一些命令并查看返回结果,因此我们需要交互式终端。
  • --rm:这个参数是说容器退出后随之将其删除。默认情况下,为了排障需求,退出的容器并不会立即删除,除非手动 docker rm。我们这里只是随便执行个命令,看看结果,不需要排障和保留结果,因此使用 --rm 可以避免浪费空间。
  • ubuntu:18.04:这是指用 ubuntu:18.04 镜像为基础来启动容器。
  • bash:放在镜像名后的是 命令,这里我们希望有个交互式 Shell,因此用的是 bash。

其他常用参数:

--name: 容器命名
-p 81:80 端口映射(前面是外部端口, 后面是docker内部端口)
-d 后台运行

列出已经下载的镜像

# 列出镜像(只有顶层镜像)
docker image list
# 列出所有镜像(中间层也列出来)
docker image ls -a

删除镜像

docker image rm [选项] <镜像1> [<镜像2> ...]

进入docker操作

docker exec -it webserver bash

保存镜像

docker commit [选项] <容器ID或容器名> [<仓库名>[:<标签>]]
# 运行一个nginx
docker run --name webserver -d -p 80:80 nginx

# 修改其中的网页
docker exec -it webserver  bash
echo '<h1>hello docker !!!</h1>' > /usr/share/nginx/html/index.html


# 保存该镜像
docker commit \
    --author "lmq" \
    --message "修改了默认网页" \
    webserver \
    nginx:v2
    
# 开启一个新的容器
docker run --name webserver2 -d -p 81:80 nginx:v2

Dockerfile定制镜像

定制 nginx 镜像为例,这次我们使用 Dockerfile 来定制。

# 在一个空白目录中,建立一个文本文件,并命名为 Dockerfile
$ mkdir mynginx
$ cd mynginx
$ touch Dockerfile


FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

这个 Dockerfile 很简单,一共就两行。涉及到了两条指令,FROM 和 RUN。

FROM:指定基础镜像

RUN: 执行命令
RUN 指令是用来执行命令行命令的。其格式有两种:

  • shell 格式:RUN <命令>,就像直接在命令行中输入的命令一样
    RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
    
  • exec 格式:RUN ["可执行文件", "参数1", "参数2"]
    FROM debian:stretch
    
    RUN apt-get update
    RUN apt-get install -y gcc libc6-dev make wget
    RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
    RUN mkdir -p /usr/src/redis
    RUN tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1
    RUN make -C /usr/src/redis
    RUN make -C /usr/src/redis install
    

Dockerfile 中每一个指令都会建立一层,RUN 也不例外。每一个 RUN 的行为,就和刚才我们手工建立镜像的过程一样:新建立一层,在其上执行这些命令,执行结束后,commit 这一层的修改,构成新的镜像。 上面的这种写法,创建了 7 层镜像, 这是完全没有意义的

上面的 Dockerfile 正确的写法应该是这样

FROM debian:stretch

RUN buildDeps='gcc libc6-dev make wget' \
    && apt-get update \
    && apt-get install -y $buildDeps \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
    && mkdir -p /usr/src/redis \
    && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
    && make -C /usr/src/redis \
    && make -C /usr/src/redis install \
    && rm -rf /var/lib/apt/lists/* \
    && rm redis.tar.gz \
    && rm -r /usr/src/redis \
    && apt-get purge -y --auto-remove $buildDeps

使用DockerFile构建镜像

docker build -t nginx:v3 .

Dockerfile指令详解

# 复制文件
COPY [--chown=<user>:<group>] SRC TARGET

# 更高级的复制文件, 原路径可以是url,下载后的文件权限为600(不推荐使用)
# add 可以自动解压缩, 需要解压缩的时候使用add
add SRC TARGET

# CMD容器启动命令
shell 格式:CMD <命令>
exec 格式:CMD ["可执行文件", "参数1", "参数2"...]

# ENTRYPOINT 入口点
ENTRYPOINT 

# ENV 设置环境变量
NV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...

# VOLUME 定义匿名卷
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>

# EXPOSE 暴露端口,EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射。
EXPOSE <端口1> [<端口2>...] 

# WORKDIR 指定工作目录
WORKDIR <工作目录路径>

#ONBUILD 为他人作嫁衣裳
ONBUILD <其它指令>

整理自:Docker —— 从入门到实践