Docker 的三要素:
Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。
镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
仓库:镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。
一个 Docker Registry 中可以包含多个 仓库(Repository);每个仓库可以包含多个 标签(Tag);每个标签对应一个镜像。
获取镜像:
从 Docker 镜像仓库获取镜像的命令是 docker pull。其命令格式为:
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
具体的选项可以通过 docker pull --help 命令看到,这里我们说一下镜像名称的格式。
Docker 镜像仓库地址:地址的格式一般是 <域名/IP>[:端口号]。默认地址是 Docker Hub。
仓库名:如之前所说,这里的仓库名是两段式名称,即 <用户名>/<软件名>。对于 Docker Hub,如果不给出用户名,则默认为 library,也就是官方镜像。
例子:
$ docker pull ubuntu:18.04
18.04: Pulling from library/ubuntu
bf5d46315322: Pull complete
9f13e0ac480c: Pull complete
e8988b5b3097: Pull complete
40af181810e7: Pull complete
e6f7c7e5c03e: Pull complete
Digest: sha256:147913621d9cdea08853f6ba9116c2e27a3ceffecf3b492983ae97c3d643fbbe
Status: Downloaded newer image for ubuntu:18.04
运行
有了镜像后,我们就能够以这个镜像为基础启动并运行一个容器。以上面的 ubuntu:18.04 为例,如果我们打算启动里面的 bash 并且进行交互式操作的话,可以执行下面的命令。
$ docker run -it --rm \ ubuntu:18.04 \ bash
root@e7009c6ce357:/# cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.1 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.1 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
docker run 就是运行容器的命令,具体格式我们会在 容器 一节进行详细讲解,我们这里简要的说明一下上面用到的参数。
-it:这是两个参数,一个是 -i:交互式操作,一个是 -t 终端。我们这里打算进入 bash 执行一些命令并查看返回结果,因此我们需要交互式终端。
--rm:这个参数是说容器退出后随之将其删除。默认情况下,为了排障需求,退出的容器并不会立即删除,除非手动 docker rm。我们这里只是随便执行个命令,看看结果,不需要排障和保留结果,因此使用 --rm 可以避免浪费空间。
ubuntu:18.04:这是指用 ubuntu:18.04 镜像为基础来启动容器。
bash:放在镜像名后的是 命令,这里我们希望有个交互式 Shell,因此用的是 bash。
进入容器后,我们可以在 Shell 下操作,执行任何所需的命令。这里,我们执行了 cat /etc/os-release,这是 Linux 常用的查看当前系统版本的命令,从返回的结果可以看到容器内是 Ubuntu 18.04.1 LTS 系统。
列出镜像
要想列出已经下载下来的镜像,可以使用 docker image ls 命令。
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
redis latest 5f515359c7f8 5 days ago 183 MB
nginx latest 05a60462f8ba 5 days ago 181 MB
mongo 3.2 fe9198c04d62 5 days ago 342 MB
00285df0df87 5 days ago 342 MB ubuntu 18.04 f753707788c5 4 weeks ago 127 MB
ubuntu latest f753707788c5 4 weeks ago 127 MB
列表包含了 仓库名、标签、镜像 ID、创建时间 以及 所占用的空间。
其中仓库名、标签在之前的基础概念章节已经介绍过了。镜像 ID 则是镜像的唯一标识,一个镜像可以对应多个 标签。因此,在上面的例子中,我们可以看到 ubuntu:18.04 和 ubuntu:latest 拥有相同的 ID,因为它们对应的是同一个镜像。
docker image ls 会列出所有顶层镜像,但是有时候我们只希望列出部分镜像。
列出特定的某个镜像,也就是说指定仓库名和标签
$ docker image ls ubuntu:18.04
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 18.04 f753707788c5 4 weeks ago 127 MB
删除本地镜像
如果要删除本地的镜像,可以使用 docker image rm 命令,其格式为:
$ docker image rm [选项] <镜像1> [<镜像2> ...]
用 ID、镜像名、摘要删除镜像
其中,<镜像> 可以是 镜像短 ID、镜像长 ID、镜像名 或者 镜像摘要。
用 docker image ls 命令来配合
像其它可以承接多个实体的命令一样,可以使用 docker image ls -q 来配合使用 docker image rm,这样可以成批的删除希望删除的镜像。我们在“镜像列表”章节介绍过很多过滤镜像列表的方式都可以拿过来使用。
比如,我们需要删除所有仓库名为 redis 的镜像:
$ docker image rm $(docker image ls -q redis)
或者删除所有在 mongo:3.2 之前的镜像:
$ docker image rm $(docker image ls -q -f before=mongo:3.2)
充分利用你的想象力和 Linux 命令行的强大,你可以完成很多非常赞的功能。
镜像是多层存储,每一层是在前一层的基础上进行的修改;而容器同样也是多层存储,是在以镜像为基础层,在其基础上加一层作为容器运行时的存储层。下面是一个 Web 服务器为例子,来讲解镜像是如何构建的。
$ docker run --name webserver -d -p 80:80 nginx
这条命令会用 nginx 镜像启动一个容器,命名为 webserver,并且映射了 80 端口,这样我们可以用浏览器去访问这个 nginx 服务器。
docker commit 的语法格式为:
docker commit [选项] <容器ID或容器名> [<仓库名>[:<标签>]]
关于Docker容器基本操作:
1.查看本地的容器进程:
[root@docker ~]# docker ps -a
2.启动容器(运行镜像)
docker run 是日常的最频繁用的命令之一,同样也是较为复杂的命令之一
命令格式:docker run[OPTIONS] IMAGE [COMMAND] [ARG...]
OPTIONS: 选项:
-i : 表示启动一个可以互动的容器
-t: 表示使用终端关联到容器的标准输入输出上
-d:表示将容器放置在后台运行
-rm: 退出后即删除容器
-name:表示要运行的镜像
COMMAND:表示启动容器时要运行的命令
3.交互式启动一个容器:
[root@docker ~]# docker run -ti stanleyws/alpine:v3.10.1 /bin/sh
[root@docker ~]# docker images | grep alpine
4.非交互式启动一个容器
[root@docker ~]# docker run --rm stanleyws/alpine:v3.10.1 /bin/echo hello
hello
5.非交互式启动一个后台容器:
[root@docker ~]# docker run -d --name myalpine stanleyws/alpine:v3.10.1 /bin/sleep 300
6.查看宿主机进程:
[root@docker ~]# ps aux | grep sleep | grep -v grep
root 49302 0.0 0.0 1540 244 ?Ss 16:45 0:00 sleep 300
7.进入容器:
[root@docker ~]# docker exec -ti myalpine /bin/sh
/ # ps aux
8.停止/启动/重启容器
1) 停止容器:
[root@docker ~]# docker stop myalpine
myalpine
[root@docker ~]# docker ps -a
[root@docker ~]# docker start/stop/restart enb098dhs348
[root@docker ~]# docker rm -f myalpine1
####过滤出已经退出的容器,再全部删除:
[root@docker ~]# for i in 'docker ps -a|grep -i exit | awk '{print $1}'';do docker rm -f $i;done
9.导出/导入镜像:
1)导出镜像
[root@docker ~]# docker images
[root@docker ~]# docker save 097834c4dr > alpine_with_1.txt.tar
[root@docker ~]# ls
alpine_with_1.txt.tar
2) 查看容器的日志:
[root@docker ~]# docker rm 83h56jsnsv90
[root@docker ~]# docker run hello-world 2>&1 >>/dev/null
[root@docker ~]# docker ps -a | grep hello
[root@docker ~]# docker logs -f 42bd19eys56g
--------------------------------------------------------------------------------------------
[root@docker ~]# docker start/stop/restart
[root@docker ~]# docker rm (-f)
[root@docker ~]# docker exec/commit
[root@docker ~]# docker logs(-f)
==============================================
10. Docker容器的高级操作:
1)映射端口:
docker run -p 容器外端口:容器内端口
2)挂载数据卷
docker run -v 容器外目录:容器内目录
3)传递环境变量
docker run -e 环境变量key=环境变量value
4)容器内安装软件(工具)
yum /apt-get/apt 等
==============================================
11.下载nginx镜像
[root@docker ~]# docker pull nginx:1.12.2
1.12.2:Pulling from library/nginx
[root@docker ~]# docker images | grep nginx
nginx 1.12.2 4037a883b034 15 months ago 108MB
[root@docker ~]# docker tag 4037a883b034 stanleyws/nginx:v1.12.2
[root@docker ~]# docker images | grep nginx
nginx 1.12.2 4037a883b034 15 months ago 108MB
stanleyws/nginx v1.12.2 4037a883b034 15 months ago 108MB
==================================================
12.映射端口:
[root@docker ~]# docker run -d -p81:80 stanleyws/nginx:v1.12.2
cf47229ea987bbe0e6e456695kzjnahaj8992jyzag902
[root@docker ~]# netstat -luntp | grep 81
tcp6 0 0 :::81 :::* LISTEN 52802/docker
13.挂载数据卷:
[root@docker ~]# mkdir html
[root@docker ~]# cd html/
[root@docker html]# wget www.baidu.com -O index.html
[root@docker ~]# docker run -d --rm --name nginx_with_baidu -d -p82:80 -v/root/html:/usr/share/nginx/html oldboy1103/nginx:v1.12.2
8c440besccs2f2ekzhi8uhgbz92nxysuajgz907hgz8qxua7
[root@docker ~]# docker ps -a
[root@docker ~]# docker exec -ti nginx_with_baidu /bin/bash
root@8c440bescc:/# cd /usr/share/nginx/html
root@8c440bescc: /usr/share/nginx/html# ls
root@8c440bescc: /usr/share/nginx/html# cat indes.html
==================================================
14. 给容器传递环境变量
[root@docker ~]# docker run --rm -e E_OPTS=abcdefg stanleyws/nginx:v1.12.2 printenv
PATH=/usr/local/sbin:/usr/local/bin/:/usr/sbin:/usr/bin:/sbin/bin
15.容器内安装软件:
[root@docker ~]# docker run -ti --rm stanleyws/nginx:v1.12.2 bash
root@b5ff598aeee7:/ curl
bash: curl : command not found
root@b5ff598aeee7:/# tee /etc/apt/sources.list << EOF
> deb http://mirrors.163.com/debian/ jessie main non-free contrib
> deb http://mirrors.163.com/debian/ jessie-updates main non-free contrib
> EOF
root@b5ff598aeee7:/ apt-get update && apt-get install curl -y