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 —— 从入门到实践