Docker 高级教程(一)
原文:Pro Docker
一、你好,Docker
Docker 是一个开发、打包和运行可移植分布式应用的开放标准平台。使用 Docker,开发人员和系统管理员可以在任何平台(如 PC、云、数据中心或虚拟机)上构建、发布和运行应用。在开发和运行应用时,获取软件应用所需的所有依赖项(包括代码、运行时库以及系统工具和库)通常是一项挑战。Docker 通过将应用所需的所有软件(包括依赖项)打包到一个称为 Docker 镜像的软件单元中,简化了应用的开发和执行,该镜像可以在任何平台和环境上运行。
Docker 映像与虚拟设备(也是软件映像(虚拟机映像))的不同之处在于,虽然每个虚拟机映像运行在单独的客户操作系统上,但 Docker 映像运行在同一个操作系统内核中。Docker 软件运行在一个被称为 Docker 容器的隔离环境中,它包含自己的文件系统和环境变量。Docker 容器相互隔离,并与底层操作系统隔离。
软件应用的 Docker 容器包括运行软件所需的所有内容,并且如果需要,文件可以从主机 OS 复制到 Docker 容器。由于应用可能需要其他软件来开发链接的应用,所以 Docker 容器可以被链接,这使得来自另一个 Docker 容器的环境变量和软件对 Docker 容器可用。
Docker 利用 docker 文件来构建映像。Dockerfile 由所有指令组成,例如下载什么软件、运行什么命令、暴露哪些网络端口、将哪些文件和目录添加到文件系统以及设置哪些环境变量。通过提供入口点,可以使停靠映像成为可执行的。可以通过提供 Docker 文件来构建 Docker 映像,或者可以从 Docker Hub ( https://hub.docker.com/ )下载预构建的 Docker 映像。Dockerfile 支持的完整指令集可以在docs.docker.com/engine/reference/builder/找到。
在这一章中,我们将在 Linux 上安装 Docker 引擎,下载 Hello World Docker 镜像,并为 Hello World 应用运行 Docker 容器。我们使用 Linux 是因为我们使用的其他一些软件,比如 Apache Hadoop,只在 Linux 上受支持(包括开发和生产)。我们使用了两个常用的 Linux 发行版,Red Hat 7 和 Ubuntu 14,但是任何支持的安装( https://docs.docker.com/v1.8/installation/ )都可以使用。
- 设置环境
- 在 Red Hat 7 上安装 Docker
- 卸载 Docker
- 安装特定的 Docker 版本
- 在 Ubuntu 上安装坞站
- 启动 Docker 服务
- 查找 Docker 服务状态
- 运行 Docker Hello World 应用
- 下载 Docker 映像
- 在 Docker 容器中运行应用
- 列出正在运行的 Docker 容器
- 在命令行上访问应用输出
- 在浏览器中访问应用输出
- 停止 Docker 容器
- 移除 Docker 容器
- 移除 Docker 映像
- 停止 Docker 服务
设置环境
我们将使用基于 Linux 的 Amazon EC2 实例来部署 Docker 和 Docker 映像。Linux 需要支持 64 位软件。我们使用了两种不同的 64 位(必需的)Amazon 机器映像(AMIs):
Ubuntu Server 14.04 LTS (HVM), SSD Volume Type - ami-d05e75b8 64 bit Red Hat Enterprise Linux version 7.1 (HVM), EBS General Purpose (SSD) Volume Type (ami-12663b7a) 64 bit
一个基于 Ubuntu AMI 的 Amazon EC2 实例如图 1-1 所示。
图 1-1。
Amazon EC2 Instance Based on Ubuntu AMI
为了连接到 Amazon EC2 实例,使用公共 IP 地址。公共 IP 地址可以从 EC2 控制台获取,如图 1-2 所示。
图 1-2。
Obtaining the Public IP Address
使用 SSH 和公共 IP 地址连接到 Amazon EC2 Ubuntu 实例,使用下面的命令,其中docker.pem是私钥格式。pem)由亚马逊 EC2 生成。
ssh -i "docker.pem" ubuntu@54.86.12.113
Ubuntu 实例的连接如图 1-3 所示。
图 1-3。
Connecting to Ubuntu Instance on Amazon EC2 from Local Host
如果使用 Red Hat AMI,连接 Amazon EC2 实例的命令会略有不同。使用“ec2-user”用户代替用户“ubuntu”。例如,使用下面的命令连接到 Linux 实例,其中docker.pem是私钥格式(。pem)由亚马逊 EC2 生成。
ssh -i "docker.pem" ec2-user@54.175.182.96
RHEL 7.1 实例的连接如图 1-4 所示。
图 1-4。
Connecting to RHEL Instance
运行以下命令,查看 Linux 体系结构是否支持 64 位软件。
uname -r
图 1-5 输出中的 x86_64 表示支持 64 位。
图 1-5。
Finding Architecture Support
在 Red Hat 7 上安装 Docker
在 Red Hat 上安装 Docker 有两种不同的方法:用 yum 安装或用脚本安装。使用 yum 安装需要用户添加 yum repo,这可能比脚本选项更复杂。我们已经使用了 Docker 安装脚本来安装 Docker。
作为拥有sudo或 root 权限的用户,使用以下命令更新本地存储库包。
sudo yum update
运行 Docker 安装脚本来安装 Docker 引擎。
curl -sSLhttps://get.docker.com/
对接发动机安装如图 1-6 所示。
图 1-6。
Installing Docker Engine
在启动 Docker 服务之前,应该修改docker.service文件来禁用 Docker 启动超时。docker.service文件在/usr/lib/systemd/system目录中,该目录设置了权限。运行 sudo 命令或将文件复制到没有权限集的目录中。例如,用下面的命令将docker.service复制到root目录。
cp /usr/lib/systemd/system/docker.service .
在 vi 编辑器中打开docker.service文件。
vi docker.service
或者以 sudo 的身份打开docker.service文件。
sudo vi /usr/lib/systemd/system/docker.service
在[Service]标题的docker.service中添加以下一行。
TimeoutStartSec=0
更新后的docker.service如图 1-7 所示。
图 1-7。
Updated docker.service
如果docker.service被复制到另一个目录,用下面的命令将文件复制回/usr/lib/systemd/system目录。
sudo cp docker.service /usr/lib/systemd/system/docker.service
刷新更改以加载新配置。
sudo systemctl daemon-reload
在红帽上安装 Docker 的所有选项都在docs . Docker . com/engine/installation/rhel/讨论。
卸载 Docker
如果在本章和后面的章节中要用到 Docker,可以跳过这一节。要卸载 Docker,请运行以下命令来列出已安装的 Docker 引擎。
yum list installed | grep docker
使用以下命令删除 Docker 引擎和 Docker 目录。
sudo yum -y remove docker-engine.x86_64
rm -rf /var/lib/docker
安装特定的 Docker 版本
要安装 Docker 的特定版本,请下载并安装该版本的 rpm。比如安装 Docker 1.7.0 如下。
curl -O -sSLhttps://get.docker.com/rpm/1.7.0/centos-6/RPMS/x86_64/docker-engine-1.7.0-1.el6.x86_64.rpm
sudo yum localinstall --nogpgcheck docker-engine-1.7.0-1.el6.x86_64.rpm
在 Ubuntu 上安装坞站
以下版本的 Ubuntu 支持 docker:Ubuntu Wily 15.10、Ubuntu Vivid 15.04、Ubuntu Trusty 14.04 (LTS)和 Ubuntu Precise 12.04 (LTS)。无论版本如何,Docker 都需要 64 位操作系统,最低 Linux 内核版本为 3.10。要找到内核版本,请在 Ubuntu 终端中运行以下命令。
uname –r
内核版本输出为 3.13,如图 1-8 ,安装 Docker 没问题。
图 1-8。
Outputting Kernel Version
在 Ubuntu 上安装 Docker 引擎之前,从以下命令开始更新 apt 源代码。
sudo apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
在“更新你的 apt 源”( http://docs.docker.com/engine/installation/ubuntulinux/ )第六节。需要你基于 Ubuntu 版本更新/etc/apt/sources.list.d/docker.list。使用以下命令可以找到 Ubuntu 发行版。
lsb_release –a
对于 Ubuntu Trusty,下面一行被添加到/etc/apt/sources.list.d/docker.list文件中。
debhttps://apt.dockerproject.org/repo
更新/etc/apt/sources.list.d/docker.list文件后运行以下命令。
sudo apt-get update
sudo apt-get purge lxc-docker*
sudo apt-cache policy docker-engine
使用以下命令安装 Ubuntu 的先决条件。
sudo apt-get update
sudo apt-get install linux-image-generic-lts-trusty
重启系统。
sudo reboot
主机系统重新启动后,使用以下命令安装 Docker。
sudo apt-get update
sudo apt-get install docker-engine
启动 Docker 服务
不管 Linux 发行版是什么,用下面的命令启动 Docker 服务。
sudo service docker start
Docker 通过 systemctl 启动,如图 1-9 中 OK 消息所示。
图 1-9。
Starting Docker Service
查找 Docker 服务状态
要验证 Docker 服务的状态,请运行以下命令。
sudo service docker status
如果 Docker 服务正在运行,则应输出如图 1-10 所示的消息 Active: active (running)。
图 1-10。
Finding Docker Service Status
运行 Docker Hello World 应用
要测试 Docker,使用下面的docker run命令运行 Hello World 应用。
sudo docker run hello-world
docker run命令将在后面的章节中介绍。如果hello-world应用运行良好,应该会生成图 1-11 中的输出,该输出是在 Red Hat 7 上生成的。
图 1-11。
Running hello-world Application
在 Ubuntu 上,对hello-world运行相同的命令。
sudo docker run hello-world
如图 1-12 所示,输出“你好,来自 Docker”消息。
图 1-12。
Running hello-world on Ubuntu
下载 Docker 映像
当我们使用docker run命令运行hello-world应用时,Docker 映像hello-world被下载,用于HelloWorld应用的 Docker 容器启动。当用于 Docker 映像的 Docker 容器启动时,可以自动下载 Docker 映像,或者可以单独下载 Docker 映像。docker pull命令用于下载 Docker 镜像。例如,运行以下命令下载 Docker 映像tutum/hello-world,这是打包成 Docker 映像的另一个HelloWorld应用。
sudo docker pull tutum/hello-world
Docker 映像是预先构建的,不需要构建。Docker 图片tutum/hello-world:latest被下载,如图 1-13 所示。后缀:latest是 Docker 映像的标签,指定了映像版本,默认情况下会下载最新版本。
图 1-13。
Downloading tutum:hello-world:latest
使用以下命令列出下载的 Docker 映像。
sudo docker images
除了之前可能已经安装的其他映像之外,tutum/hello-world Docker 映像被列出,如图 1-14 所示。
图 1-14。
Listing Docker Images
在 Docker 容器中运行应用
docker run命令用于在一个单独的容器中运行一个进程,这是应用的另一个术语。docker run命令的语法如下。
docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...]
唯一需要的命令参数是 Docker 映像。Docker 容器可以在分离模式(或后台)或前台模式下启动。在分离模式下,进程的 stdin、stdout 和 stderr 流与运行docker run命令的命令行分离。要在分离模式下启动容器,设置–d=true或仅设置–d。默认模式是前台模式,在这种模式下,容器在前台启动,stdin、stdout 和 stderr 流连接到主机命令行控制台。–name选项可用于指定 Docker 容器的名称。–p选项用于为容器中运行的进程指定一个端口。例如,使用–d参数在分离模式下为tutum/hello-world映像启动一个 Docker 容器,使用–p参数将容器名设为helloapp,将应用运行的端口设为 80。
sudo docker run -d -p 80 --name helloapp tutum/hello-world
Docker 容器启动,如图 1-15 所示。
图 1-15。
Running an Application in a Docker Container
可以启动交互式外壳或终端(tty)来运行应用于在容器中运行的进程的命令。交互终端启动时,–i和–t命令参数一起使用或组合为–it。关于docker run命令的完整语法,参见 http://docs.docker.com/engine/reference/run/ 。
列出正在运行的 Docker 容器
要列出正在运行的 Docker 容器,请运行以下命令。
sudo docker ps
helloapp容器被列出,如图 1-16 所示。容器 id 也被分配给容器。在所有 docker 命令中,如docker stop、docker start,可以使用容器名或容器 id。
图 1-16。
Listing only the Docker Containers that are Running
在 PORTS 列中,分配给容器中端口 80 上运行的进程的外部端口被列为 32768。当从容器外部访问helloapp应用时,必须使用 32768 端口(不是端口 80)。也可以使用docker port命令列出外部端口。
sudo docker port 82171f7ade46
端口 32768 被列出,如图 1-17 所示。0.0.0.0 主机 IP 地址意味着本地机器上的所有 IP 地址。
图 1-17。
Listing Port
要列出所有正在运行或已退出的 Docker 容器,请运行以下命令。
sudo docker ps –a
在命令行上访问应用输出
curl 工具可用于连接运行helloapp的主机和端口。运行以下命令来访问外部端口 32768 上的应用。
curl http://localhost:32768
helloapp生成的 HTML 在主机中得到输出,如图 1-18 所示。
图 1-18。
Output from helloapp Application
在浏览器中访问应用输出
然而,使用 curl 工具访问生成 HTML 输出的应用并不总是最好的方法。在本节中,我们将在浏览器中访问helloapp。如果浏览器与运行 Docker 容器的主机在同一台机器上,url http://localhost:32768可以用来显示应用输出。但是如果浏览器在不同的主机上,就像本章中的例子一样,Amazon EC2 实例的公共 DNS 必须用来访问应用。公共 DNS 可以从亚马逊 EC2 控制台获得,如图 1-19 所示。
图 1-19。
Finding Public DNS
使用公共 DNS,通过 URL http://ec2-54-86-12-113.compute-1.amazonaws.com:32768/ 在远程浏览器中访问helloapp,该浏览器可以运行在 Windows 操作系统上。Docker 容器helloapp中运行的应用生成的输出显示在浏览器中,如图 1-20 所示。
图 1-20。
Displaying Output from helloapp in a Browser
停止 Docker 容器
Docker 容器可以用docker stop命令停止。例如,用下面的命令停止helloapp容器。
sudo docker stop helloapp
Docker 容器被停止。随后运行docker ps命令列出正在运行的容器。如图 1-21 所示helloapp容器未列出。
图 1-21。
Stopping a Container
移除 Docker 容器
Docker 容器可通过docker rm命令移除。例如,用下面的命令删除helloapp容器。
sudo docker rm helloapp
在移除容器之前,必须停止 Docker 容器。
移除 Docker 映像
要删除 Docker 映像,请运行 docker rmi 命令。例如,运行以下命令删除 Docker 映像 tutum/hello-world。
sudo docker rmi tutum/hello-world
在删除 Docker 映像之前,必须停止并删除所有访问 Docker 映像的容器。有时,一些未完全下载的 Docker 映像可以用docker images命令列出。此类 Docker 映像没有指定名称,而是被列为<>。所有这样的悬挂映像都可以用下面的命令删除。
sudo docker rmi $(sudo docker images -f "dangling=true" -q)
如图 1-22 中的输出所示,多个 Docker 映像被移除。
图 1-22。
Removing Dangling Docker Images
停止 Docker 服务
要停止 Docker 服务,请运行以下命令。
sudo service docker stop
可以使用以下命令再次启动 Docker 服务。
sudo service docker start
或者,可以使用以下命令重新启动正在运行的 Docker 服务。
sudo service docker restart
摘要
在本章中,我们介绍了 Docker 引擎。我们在两个 Linux 发行版上安装了 Docker:Red Hat 7 和 Ubuntu,但 Docker 也可能安装在其他 Linux 发行版上。对于支持的 Docker 安装操作系统,请参考docs.docker.com/v1.8/installation/。我们讨论了下载 Docker 映像、使用 Docker 映像运行 Docker 容器、从远程浏览器访问 Docker 容器应用,以及停止和删除 Docker 容器和 Docker 映像。在下一章,我们将在 Docker 容器中运行 Linux。
二、安装 Linux
安装 Linux 是大多数开发人员和所有 Linux 管理员都熟悉的任务。有几种 Linux 发行版,包括 Red Hat Linux、Ubuntu、openSuse 和 Oracle Linux。安装 Linux 的一些选项包括使用 Amazon Linux AMIs、ISO 映像和虚拟机映像。Linux 也可以使用 Docker 镜像来安装。Docker 公共存储库( https://hub.docker.com/ )提供了几个用于 Linux 发行版的 Docker 映像。在本章中,我们将使用 Docker 映像安装 Oracle Linux。
- 设置环境
- 下载 Docker 映像
- 列出 Docker 映像
- 以分离模式运行容器
- 在前台运行容器
- 列出 Docker 容器
- 查找 Oracle Linux 容器信息
- 列出容器进程
- 启动交互式 Shell
- 创建容器
- 停止容器
- 移除容器
设置环境
本章需要以下软件:
- -Docker(使用 1.8.x 版本)
- -适用于 Oracle Linux 的 docker image
- -主机 Linux 操作系统(使用 Amazon EC2 AMI)
对于主机操作系统,我们在 Amazon EC2 上使用了 Red Hat Enterprise Linux 7.1 (HVM),SSD 卷类型- ami-12663b7a。使用以下命令登录 Amazon EC2 实例;不同用户的 IP 地址(54.165.251.73)会有所不同,可以按照附录 a 中的说明获取
ssh -i "docker.pem" ec2-user@54.165.251.73
按照第一章中的说明安装 Docker。用下面的命令启动 Docker。
sudo service docker start
一条 OK 消息表明 Docker 已经启动。要确认 Docker 已经开始运行以下命令。
sudo service docker status
如果 Active:标签具有如图 2-1 所示的活动(运行)值,则 Docker 已经启动并准备在 Docker 容器中部署应用。
图 2-1。
Finding Docker Status
下载 Docker 映像
我们使用了 Docker Hub 存储库中的 Docker 映像oraclelinux(Hub . Docker . com/_/Oracle Linux/)。使用以下命令下载最新版本的oraclelinux Docker 映像。
sudo docker pull oraclelinux
Docker 映像被标记到映像名称,以区分映像的变体(或版本)。例如,要下载oraclelinux 6.6 版本,运行以下命令。
sudo docker pull oraclelinux:6.6
要下载oraclelinux 7 版本,运行以下命令。
sudo docker pull oraclelinux:7
如图 2-2 中的输出所示,下载oraclelinux 6.6 和 7 版本的 Docker 映像。
图 2-2。
Downloading Docker Images
列出 Docker 映像
可以使用以下命令列出下载并可用于运行应用的 Docker 映像。
sudo docker images
两张oraclelinux图片;版本 6.6 和 7 如图 2-3 所示。标签列列出了映像的版本(或变体)。
图 2-3。
Listing Docker Images
以分离模式运行容器
docker run命令用于运行容器中的进程。docker run命令可以在分离模式或连接模式下运行。在分离模式下,容器与命令行分离,I/O 通过网络和共享卷完成。下面的命令语法将以分离模式运行 Docker 容器,如–d选项所示。–name选项设置容器的名称。
sudo docker run –d --name <container-name> <image-name>
如果使用–d 选项指定–I–t 选项,则不会启动交互式终端或 shell。例如,运行以下命令,使用标签为 6.6 的oraclelinux Docker 映像以分离模式启动名为oraclelinux的容器。
sudo docker run –i –t –d --name oraclelinux6 oraclelinux:6.6
即使指定了–i和–t选项,容器还是以分离模式运行,如图 2-4 所示。
图 2-4。
Starting Docker Container in Detached Mode
在分离模式下,Docker 容器与 STDIN、STDOUT 和 STDERR 流分离。–RM 选项不能在分离模式下使用。关于docker run命令语法的详细信息,请参考docs . docker . com/engine/reference/run/。
在前台运行容器
要在附加模式下运行 Docker 容器,省略–d选项。
sudo docker run <image-name>
在附加模式下,启动一个容器进程并将其附加到所有标准流(STDIN、STDOUT 和 STDERR)。–name选项也可在附加模式下用于指定容器名称。要启动一个交互式终端,使用–i和–t选项,这将为容器进程分配一个 tty。如果指定了–RM 选项,则会在容器退出后清理容器资源,包括分配给容器的文件系统。运行以下命令,使用oraclelinux:7.0 Docker 映像运行容器进程;–name选项为容器指定一个名称,–i –t选项启动一个交互终端(tty),–rm选项在容器退出后清理容器。
sudo docker run –i –t –rm –name oraclelinux7 oraclelinux:7.0
使用oracleinux映像的 Docker 容器进程启动并连接到一个交互式 shell 或 tty,如图 2-5 所示。
图 2-5。
Starting Docker Container in Attached Mode
容器名称必须唯一。如果启动了与正在运行的容器同名的容器,则会产生如图 2-6 所示的错误。
图 2-6。
Container Name must be Unique
列出 Docker 容器
Docker 容器可以运行,也可以不运行。运行以下命令列出正在运行的 Docker 容器。
sudo docker ps
唯一运行的容器oraclelinux:6.6和oraclelinux:7.0如图 2-7 所示。“状态”列指示容器是“启动”并正在运行还是“已退出”。容器 ID 列列出了容器 ID。
图 2-7。
Listing Running Docker Containers
要列出所有正在运行或已退出的容器,请运行以下命令。
sudo docker ps –a
已经退出的容器也会被列出,如图 2-8 所示。
图 2-8。
Listing All Docker Containers
查找 Oracle Linux 容器信息
可以用docker inspect命令列出一个容器的信息。运行以下命令列出有关容器 oraclelinux7 的信息。
sudo docker inspect oraclelinux7
容器细节以 JSON 格式列出,如图 2-9 所示。
图 2-9。
Output from docker inspect
列出容器进程
用docker top命令列出容器正在运行的进程。下面的命令列出了由oraclelinux6容器运行的进程。
sudo docker top oraclelinux6
如图 2-10 所示,UID 和 PID 在为进程列出的列中。
图 2-10。
Listing Container Processes
启动交互式 Shell
当使用附加模式和–i –t选项使用docker run命令启动容器进程时,可以启动交互式 shell 或 tty,以指示交互式终端。
sudo docker run –i –t --rm <image-name>
运行以下命令来运行 oraclelinux:7.0 映像的容器并启动 tty 终端。
sudo docker run –i –t --rm –name oraclelinux7 oraclelinux:7.0
如图 2-11 所示,一个交互式 shell 启动,容器进程连接到终端。
图 2-11。
The interactive shell gets started when a Docker container is started in Attached Mode
如果已经使用–d选项在分离模式下启动了容器进程,可以使用以下命令语法启动交互式终端。
docker exec -i -t <container> bash
–i和–t选项可以合并成–it。运行下面的命令为oraclelinux6容器启动一个 tty。
sudo docker exec –it oraclelinux6 bash
交互式 tty 启动,如图 2-12 所示。
图 2-12。
Starting an Interactive Terminal for a Docker Docker Container running in Detached Mode
无论 tty 是在使用–rm、-it选项启动容器进程时启动,还是随后使用前面的命令启动,容器命令都可以在交互式 shell 中运行。在交互式外壳中运行的命令指向在容器中运行的软件或应用。例如,如果 Docker 容器运行 Oracle Linux,则 tty 命令适用于 Oracle Linux 平台。例如,使用以下命令输出 Oracle 版本。
cat /etc/oracle-release
Oracle Linux Server 版如图 2-13 所示。
图 2-13。
Outputting Oracle Release
运行其他一些 Linux 命令来创建一个目录,设置该目录的权限,并列出文件和目录。
mkdir /orcl
chmod 777 /orcl
ls -l
/orcl目录被创建并被列出,如图 2-14 所示。
图 2-14。
Listing Files and Directories
运行exit命令退出交互 shell,如图 2-15 所示。
图 2-15。
Running the exit Command
创建容器
docker create命令用于创建一个容器。运行以下命令为oraclelinux:6.6映像创建一个名为orcl6的容器。即使指定了–i –t选项,交互式 shell 也不会启动。
docker create -i -t --name orcl6 oraclelinux:6.6 /bin/bash
要启动 Docker 容器orcl6和用于orcl6容器的交互式 shell,运行docker start命令。-a和-i选项将当前 shell 的标准输入、标准输出和标准错误流附加到容器中。所有信号都被转发到容器。
sudo docker start –a –i orcl6
Docker 容器 orcl6 和一个交互 shell 开始如图 2-16 所示。
图 2-16。
Starting an Interactive Shell with docker start
停止容器
要停止正在运行的容器,运行docker stop命令。运行以下命令来停止orcl6容器。
sudo docker stop orcl6
orcl6 容器停止,如图 2-17 所示。
图 2-17。
Stopping a Docker Container
随后,docker ps –a命令会将orcl6容器列为“已退出”,如图 2-18 所示。
图 2-18。
Listing an Exited Container
移除容器
要移除容器,运行docker rm命令。移除前必须先停止容器,否则docker rm命令不会移除容器。运行以下命令删除orcl6容器。
sudo docker rm orcl6
orcl6 容器被移除,如图 2-19 所示。
图 2-19。
Removing A Docker Container
摘要
在本章中,我们在 Docker 容器中安装了 Oracle Linux。我们讨论了如何下载 Docker 映像并运行容器进程。我们还讨论了使用不同的映像标签、启动交互式 shell、运行容器的不同模式,以及启动、停止和删除容器。在下一章,我们将讨论在 Docker 容器中运行 Oracle 数据库。
三、使用 Oracle 数据库
Oracle 数据库是最常用的关系数据库。关系数据库基于固定的模式,存储的基本单位是表。Docker Hub 在公共存储库中有几个针对 Oracle 数据库的 Docker 映像。在本章中,我们将使用 Oracle 数据库的 Docker 映像在 Linux 上安装和使用数据库。本章包括以下几节。
- 设置环境
- 启动 Oracle 数据库
- 列出容器日志
- 正在启动 SQL* Plus
- 创建用户
- 创建数据库表
- 正在删除 Oracle 数据库
设置环境
本章需要以下软件。
- -Docker 引擎(使用 1.8 版)
- oracle 数据库的 docker image
我们使用了一个 Amazon EC2 实例,使用 Red Hat Linux 7 作为操作系统。首先,SSH 登录到 Amazon EC2 实例。对于不同的用户,IP 地址是不同的。
ssh -i "docker.pem" ec2-user@54.175.172.33
查找 Docker 引擎的状态。
sudo service docker status
如果 Docker 引擎没有运行,请启动 Docker 服务。
sudo service docker start
下载sath89/oracle-xe-11g Docker 映像。
sudo docker pull sath89/oracle-xe-11g
下载sath89/oracle-xe-11g的最新映像,如图 3-1 所示。
图 3-1。
Downloading Docker Image for Oracle Database
列出 Docker 映像。
sudo docker images
sath89/oracle-xe-11g 映像被列出,如图 3-2 所示。
图 3-2。
Listing Docker Images
启动 Oracle 数据库
接下来,用docker run命令在 Docker 容器中启动一个 Oracle 数据库实例。为 Oracle Application Express 管理控制台指定 8080 端口,为 Oracle 数据库监听程序指定 1521 端口。用–name选项指定容器名称。
docker run --name orcldb -d -p 8080:8080 -p 1521:1521 sath89/oracle-xe-11g
Oracle 数据库在 Docker 容器中启动,如图 3-3 所示。
图 3-3。
Starting Oracle Database in a Docker Container
用下面的命令列出 Docker 容器。
sudo docker ps
orcldb容器被列出,如图 3-4 所示。
图 3-4。
Listing Docker Containers that are Running
Oracle 数据库的主机名、端口、SID、用户名和口令如下。
hostname: localhost
port: 1521
sid: xe
username: system
password: oracle
列出容器日志
要列出容器日志,运行docker logs命令。
sudo docker logs -f c0fa107a43d2
容器日志列表如图 3-5 所示。Oracle 数据库日志包括数据库初始化和配置。
图 3-5。
Listing Docker Container Log
更详细的 Docker 容器日志如下。
[ec2-user@ip-172-30-1-192 ∼]$ sudo docker logs -f c0fa107a43d2
Database not initialized. Initializing database.
Setting up:
processes=500
sessions=555
transactions=610
If you want to use different parameters set processes, sessions, transactions env variables and consider this formula:
processes=x
sessions=x*1.1+5
transactions=sessions*1.1
Oracle Database 11g Express Edition Configuration
-------------------------------------------------
This will configure on-boot properties of Oracle Database 11g Express
Edition. The following questions will determine whether the database should
be starting upon system boot, the ports it will use, and the passwords that
will be used for database accounts. Press <Enter> to accept the defaults.
Ctrl-C will abort.
Specify the HTTP port that will be used for Oracle Application Express [8080]:
Specify a port that will be used for the database listener [1521]:
Specify a password to be used for database accounts. Note that the same
password will be used for SYS and SYSTEM. Oracle recommends the use of
different passwords for each database account. This can be done after
initial configuration:
Confirm the password:
Do you want Oracle Database 11g Express Edition to be started on boot (y/n) [y]:
Starting Oracle Net Listener...Done
Configuring database...Done
Starting Oracle Database 11g Express Edition instance...Done
Installation completed successfully.
Database initialized. Please visit http://#containeer:8080/apex to proceed with configuration
Oracle Database 11g Express Edition instance is already started
Database ready to use. Enjoy! ;)
[ec2-user@ip-172-30-1-192 ∼]$
正在启动 SQL* Plus
使用以下命令启动交互式 shell。容器 ID 很可能不同。
sudo docker exec -it c0fa107a43d2 bash
关于 bash 的更多细节请参考 http://www.gnu.org/software/bash/manual/bash.html#Bash-Startup-Files 。在 tty 中运行以下命令。术语“tty”、“交互式外壳”和“交互式终端”可以互换使用。
sqlplus
当提示输入如图 3-6 所示的用户名时,指定“系统”。
图 3-6。
Starting SQL*Plus
当提示输入密码时,请指定“oracle”。与 Oracle Database 11g Express 建立连接。SQL*Plus 启动,显示 SQL >提示符,如图 3-7 所示。
图 3-7。
SQL*Plus Shell Prompt
我们使用容器 id 来启动交互式 tty 终端。或者,容器名称可以如下使用。
sudo docker exec -it orcldb bash
创建用户
要创建一个名为OE的用户,在SYSTEM表空间上拥有无限配额,密码为“OE ”,运行以下命令。
SQL> CREATE USER OE QUOTA UNLIMITED ON SYSTEM IDENTIFIED BY OE;
Grant the CONNECT and RESOURCE roles to the OE user.
GRANT CONNECT, RESOURCE TO OE;
创建用户“OE”并授予角色,如图 3-8 所示。
图 3-8。
Creating User OE
创建数据库表
使用以下 SQL 语句在“OE”模式中创建一个名为“Catalog”的数据库。
SQL> CREATE TABLE OE.Catalog(CatalogId INTEGER PRIMARY KEY,Journal VARCHAR2(25),Publisher VARCHAR2(25),Edition VARCHAR2(25),Title VARCHAR2(45),Author VARCHAR2(25));
表格“目录”被创建,如图 3-9 所示。
图 3-9。
Creating Oracle Database Table OE.Catalog
使用下面的INSERT SQL 语句将数据添加到目录表中。
SQL> INSERT INTO OE.Catalog VALUES('1','Oracle Magazine','Oracle Publishing','November December 2013','Engineering as a Service','David A. Kelly');
增加一行数据,如图 3-10 所示。
图 3-10。
Adding Data to OE.Catalog Table
使用下面的SELECT语句运行 SQL 查询。
SQL> SELECT * FROM OE.CATALOG;
添加的一行数据被列出,如图 3-11 所示。
图 3-11。
Running a SQL Query
要退出 SQL*Plus,指定退出命令,如图 3-12 所示。
图 3-12。
Exiting SQL*Plus
正在删除 Oracle 数据库
要删除运行 Oracle 数据库实例的容器,运行下面的docker rm命令。
sudo docker rm c0fa107a43d2
要删除 Docker 映像 sath89/oracle-xe-11g,请运行以下命令。
sudo docker rmi sath89/oracle-xe-11g
Docker 容器和映像被移除,如图 3-13 所示。
图 3-13。
Removing Docker Image
摘要
在本章中,我们使用 Docker 映像在 Amazon EC2 实例上安装 Oracle Database 11g XE。我们登录到 SQL*Plus 并创建了一个数据库表来演示 Docker 容器中运行的 Oracle 数据库的使用。在下一章,我们将在 Docker 容器中运行 MySQL 数据库。
四、使用 MySQL 数据库
MySQL 是最常用的开源关系数据库。MySQL 在某些方面类似于 Oracle 数据库,例如数据库将用户保存在授权表中。但是 MySQL 在某些方面也不同于 Oracle 数据库:
MySQL does not have roles and privileges have to be granted individually to users. Database and table names are case-insensitive in Oracle but are case sensitive if the underlying OS is case-sensitive. MySQL provides a default value for columns that do not allow a NULL value and a value is not provided explicitly in the INSERT statement, if the strict mode is not enabled. Oracle database does not generate a default value for columns with the NOT NULL constraint. MySQL database supports AUTO_INCREMENT for a column while a Sequence is used in Oracle Database. Some of the data types in MySQL are different. For example, MySQL does not support the VARCHAR2 data type.
在本章中,我们将在 Docker 容器中运行 MySQL 数据库。本章包括以下几节。
- 设置环境
- 启动 MySQL CLI Shell
- 设置要使用的数据库
- 创建数据库表
- 添加表格数据
- 查询表
- 列出数据库和表格
- 离开 TTY 终点站
- 启动另一个 MySQL 服务器实例
- 列出 Docker 容器日志
设置环境
本章需要以下软件。
- -Docker 引擎(使用 1.8 版)
- MySQL 数据库的 Docker 映像
使用 Amazon EC2 实例的公共 IP 地址登录到该实例。
ssh -i "docker.pem" ec2-user@52.91.169.69
启动 Docker 服务。
sudo service docker start
验证 Docker 服务正在运行。
sudo service docker status
如图 4-1 所示,来自docker start命令的输出应该正常,并且来自docker status命令的输出对于活动字段应该是活动的(运行中)。
图 4-1。
Starting Docker Service and verifying Status
Docker Hub 提供了一个官方的 Docker 映像。使用以下命令下载 Docker 映像。
sudo docker pull mysql
最新的 Docker 映像mysql:latest被下载,如图 4-2 所示。
图 4-2。
Downloading Docker Image for MySQL Database
使用以下命令列出 Docker 映像。
sudo docker images
mysql映像被列出,如图 4-3 所示。
图 4-3。
Listing Docker Image for MySQL Database
启动 MySQL 服务器
在这一节中,我们将在 Docker 容器中运行 MySQL 数据库。MySQL 数据库默认使用/var/lib/mysql目录存储数据,但是也可以使用另一个目录。我们将使用/mysql/data目录来存储 MySQL 数据。创建/mysql/data目录,并将其权限设置为全局(777)。
sudo mkdir -p /mysql/data
sudo chmod -R 777 /mysql/data
/mysql/data目录被创建,如图 4-4 所示。
图 4-4。
Creating the Data Directory
当运行docker run命令在 Docker 容器中启动 MySQL 时,可能会指定某些环境变量,如下表所述。
除了MYSQL_ROOT_PASSWORD环境变量,所有其他变量都是可选的,但是我们将使用所有环境变量运行一个 MySQL 实例容器。我们将使用以下命令参数运行docker run命令。
环境变量用–e指定。运行下面的docker run命令在 Docker 容器中启动一个 MySQL 实例。
sudo docker run -v /mysql/data:/var/lib/mysql --name mysqldb -e MYSQL_DATABASE='mysqldb' -e MYSQL_USER='mysql' -e MYSQL_PASSWORD='mysql' -e MYSQL_ALLOW_EMPTY_PASSWORD='yes' -e MYSQL_ROOT_PASSWORD='' -d mysql
docker run命令的输出如图 4-5 所示。
图 4-5。
Running MySQL Database in a Docker Container
运行以下命令,列出正在运行的 Docker 容器。
sudo docker ps
运行 MySQL 数据库实例的 Docker 容器mysqldb如图 4-6 所示。
图 4-6。
Listing Docker Containers
启动 MySQL CLI Shell
接下来,我们将登录 MySQL CLI shell。但是首先我们需要启动一个交互式终端来运行mysql命令来启动 MySQL CLI。使用以下命令启动交互式终端或 shell。
sudo docker exec -it mysqldb bash
在交互式终端中运行以下命令。
mysql
MySQL CLI 启动,如图 4-7 所示。
图 4-7。
Starting MySQL CLI
也可以使用容器 id 而不是容器名称来启动交互式终端。
sudo docker exec -it 969088c84a4f bash
设置要使用的数据库
使用“use”命令设置数据库。默认情况下,Docker 容器中启动的 MySQL 数据库不提供“测试”数据库。如果运行“use test”命令,将输出以下错误消息。
mysql> use test
ERROR 1049 (42000): Unknown database 'test'
当我们用docker run命令启动 MySQL 数据库的 Docker 容器时,我们创建了一个名为“mysqldb”的数据库。使用以下命令将数据库设置为“mysqldb”。
mysql> use mysqldb
前面命令的输出如下。数据库被设置为“mysqldb”,如图 4-8 所示。
图 4-8。
Setting Database to mysqldb
创建数据库表
接下来,创建一个名为“Catalog”的数据库表,其中包含列 CatalogId、Journal、Publisher、Edition、Title 和 Author。运行以下 SQL 语句。
mysql> CREATE TABLE Catalog(CatalogId INTEGER PRIMARY KEY,Journal VARCHAR(25),Publisher VARCHAR(25),Edition VARCHAR(25),Title VARCHAR(45),Author VARCHAR(25));
Catalog表被创建,如图 4-9 所示。
图 4-9。
Creating a MySQL Database Table
添加表格数据
使用以下 INSERT 语句将数据添加到目录表中。
mysql> INSERT INTO Catalog VALUES('1','Oracle Magazine','Oracle Publishing','November December 2013','Engineering as a Service','David A. Kelly');
一行数据被添加到目录表中,如图 4-10 所示。
图 4-10。
Adding a Row of Data to MySQL Table
查询表
接下来,用 SQL 查询查询目录表。以下 SELECT 语句选择目录表中的所有数据。
mysql> SELECT * FROM Catalog;
添加的一行数据被列出,如图 4-11 所示。
图 4-11。
Running a SQL Query
在本章使用的操作系统(RHEL 7.1 操作系统)上,MySQL 表名区分大小写。如果使用了表名Catalog的变体,就会产生错误。例如,在 SQL 查询中使用表名CATALOG,会产生如图 4-12 所示的错误。
图 4-12。
The table name is Case-sensitive in MySQL
列出数据库和表格
可以在 MySQL CLI 中使用以下命令列出 MySQL 服务器实例中的数据库。
mysql> show databases;
数据库被列出,包括新创建的数据库“mysqldb”,如图 4-13 所示。
图 4-13。
Listing MySQL Databases
离开 TTY 终点站
使用“Exit”命令退出 MySQL CLI。
mysql> exit
Bye
使用“Exit”命令退出交互式 shell 或 tty。
root@969088c84a4f:/# exit
exit
前面命令的输出如图 4-14 所示。
图 4-14。
Exiting MySQL CLI
停止 Docker 容器
用docker stop命令停止 Docker 容器。
[ec2-user@ip-172-30-1-192 ∼]$ sudo docker stop 969088c84a4f
969088c84a4f
随后,用docker ps命令列出正在运行的 Docker 容器。mysqldb容器没有被列出。
sudo docker ps
[ec2-user@ip-172-30-1-192 ∼]$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
在下一节中,我们将创建另一个 MySQL 服务器实例,就像我们在本章前面创建 MySQL 服务器实例一样。但是我们不能使用与现有容器相同的容器名。如果 Docker 容器名称不同,则可以启动运行 MySQL 数据库或任何其他软件的另一个 Docker 容器。如果我们创建一个 Docker 容器来运行另一个名为“mysqldb”的 MySQL 服务器,就会产生一个错误。例如,运行下面的docker run命令创建另一个名为“mysqldb”的容器。
sudo docker run --name mysqldb -e MYSQL_ROOT_PASSWORD=mysql -d mysql
下面的错误会得到输出。
Error response from daemon: Conflict. The name "mysqldb" is already in use by container 969088c84a4f. You have to delete (or rename) that container to be able to reuse that name.
要创建一个名为“mysqldb”的新 Docker 容器,首先删除已经用docker rm命令创建的“mysqldb”容器。容器 id 或容器名称可用于容器的 docker 命令,如stop、start和rm。
sudo docker rm 969088c84a4f
启动另一个 MySQL 服务器实例
删除“mysqldb”容器后,用docker run命令再次创建容器。我们将以不同的方式创建新的“mysqldb”容器。为第二次运行docker run命令指定不同的环境变量。仅指定所需的环境变量MYSQL_ROOT_PASSWORD,并将其值设置为“mysql”。
sudo docker run --name mysqldb -e MYSQL_ROOT_PASSWORD=mysql -d mysql
随后,使用以下命令启动交互式 shell。
sudo docker exec -it 113458c31ce5 bash
在交互式 shell 中使用以下命令登录 MySQL CLI。
mysql –u root –p mysql
指定“root”用户的密码,即mysql。MySQL CLI 启动如图 4-15 所示。
图 4-15。
Using a Password to Start MySQL CLI
也可以发出如下的mysql命令。
mysql –u root –p
指定“mysql”用户的密码。MySQL CLI 启动如图 4-16 所示。
图 4-16。
Alternative mysql Login command
下面的mysql命令不会启动 MySQL CLI。
root@113458c31ce5:/# mysql -u root
将生成以下错误。
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
用show databases命令列出数据库。默认数据库包括“mysql”数据库,如图 4-17 所示。之前,“mysqldb”数据库也与show databases命令一起列出,因为“mysqldb”数据库是在运行docker run命令时创建的。
图 4-17。
Listing the Default Databases
使用“使用 mysql”命令将数据库设置为“mysql”数据库,如图 4-18 所示。
图 4-18。
Using the mysql Database
用show tables命令列出mysql数据库中的数据库表,如图 4-19 所示。
图 4-19。
Listing Tables
列出 Docker 容器日志
接下来,用docker logs命令列出mysqldb容器的日志。
sudo docker logs -f mysqldb
mysqldb容器的日志列表如图 4-20 所示。
图 4-20。
Listing Docker Container Log
摘要
在这一章中,我们使用 Docker 镜像在 Docker 容器中运行 MySQL 服务器。我们运行了两种不同的docker run命令;一个包括所有可能为“mysql”映像设置的环境变量,另一个只包括必需的环境变量。在下一章中,我们将讨论在 Docker 上运行 MongoDB。
五、使用 MongoDB
MongoDB 是最常用的 NoSQL 数据库。MongoDB 基于文档存储数据模型,将数据存储为 BSON(二进制 JSON)文档。MongoDB 提供了一种灵活的无模式存储格式,其中不同的记录可以有不同的字段,这意味着没有应用固定的数据结构。字段值没有关联的数据类型,不同的字段可能具有不同的数据类型。有了 JSON 格式,数据结构的层次变得可行,一个字段可以使用一个数组存储多个值。在本章中,我们将使用 Docker 映像在 Docker 容器中运行 MongoDB。本章包括以下几节。
- 设置环境
- 正在启动 MongoDB
- 启动交互式终端
- 启动 Mongo Shell
- 创建数据库
- 创建收藏
- 创建文档
- 查找文档
- 添加另一个文档
- 删除收藏
- 添加一批文档
- 更新文档
- 查询单个文档
- 查询所有文档
- 制作数据备份
- 停止和重新启动 MongoDB 数据库
- 删除文档
- 退出 Mongo Shell
设置环境
本章需要以下软件:
- -Docker 引擎(版本 1.8)
- -蒙戈布坞站映像
我们使用了一个 Amazon EC2 实例(Amazon Machine Image Red Hat Enterprise Linux 7.1(HVM),SSD 卷类型- ami-12663b7a)来安装 Docker 映像,并在 Docker 容器中运行 MongoDB。到 Amazon EC2 实例的 SSH 登录。
ssh -i "docker.pem" ec2-user@54.174.254.96
启动 Docker 服务。
sudo service docker start
验证 Docker 服务状态。
sudo service docker status
Docker 服务应该是活动的(正在运行),如图 5-1 所示。
图 5-1。
Starting Docker Service and verifying Status
下载 MongoDB 数据库的官方 Docker 映像。
sudo docker pull mongo:latest
列出 Docker 映像。
sudo docker images
名为“mongo”的 Docker 映像被列出,如图 5-2 所示。
图 5-2。
Downloading Docker Image mongo
正在启动 MongoDB
接下来,在 Docker 容器中启动 MongoDB。MongoDB 默认将数据存储在 Docker 容器的/data/db目录中。一个目录可以从底层主机系统挂载到运行 MongoDB 数据库的容器。例如,在主机上创建一个目录/data。
sudo mkdir -p /data
在 mongo 映像上使用docker run命令启动 Docker 容器,将容器中的/data目录挂载为主机上的/data目录。将容器名称指定为“mongodb”。
sudo docker run -t -i -v /data:/data --name mongodb -d mongo
Docker 容器和容器中的 MongoDB 服务器如图 5-3 所示启动。
图 5-3。
Starting Docker Container for MongoDB
列出正在运行的 Docker 容器。
sudo docker ps
如图 5-4 所示,mongodb容器被列为在端口 27017 上运行。
图 5-4。
Listing Docker Container for MongoDB
MongoDB 端口也可以使用–p选项显式指定。
docker run -t -i -v /data:/data -p 27017:27017 --name mongodb -d mongo
可以使用docker logs命令列出容器日志。
sudo docker logs mongodb
启动交互式终端
使用以下命令启动交互式终端(tty)。
sudo docker exec -it mongodb bash
启动 Mongo Shell
要启动 MongoDB shell,请运行以下命令。
mongo
MongoDB shell 启动,并显示>提示符,如图 5-5 所示。
图 5-5。
Starting MongoDB Shell from TTY
MongoDB shell 也可以在特定的主机和端口上启动,如下所示。
mongo –host localhost –port 27017
MongoDB shell 在主机localhost,端口 27017 上启动,如图 5-6 所示。“测试”数据库实例被连接到。
图 5-6。
Starting MongoDB Shell using Host and Port
或者,可以只指定主机或端口中的一个来启动 MongoDB shell。
mongo –port 27017
MongoDB shell 在127.0.0.1:27071/test启动并连接到 MongoDB 服务器,如图 5-7 所示。
图 5-7。
Starting MongoDB Shell using only the Port
指定主机和端口的另一种形式是host:port。例如,用下面的命令启动 MongoDB shell 并连接到localhost:27017。
mongo localhost:27017
MongoDB Shell 连接到localhost:27017/test数据库,如图 5-8 所示。
图 5-8。
Starting MongoDB Shell using host:port Format
创建数据库
使用下面的命令帮助方法(也称为命令助手)从 MongoDB shell 中列出数据库。
show dbs
当数据库名称设置为要创建的数据库时,会隐式创建一个新数据库。例如,用下面的命令将数据库设置为“mongodb”。
use mongodb
show dbs 命令帮助方法在使用数据库之前不会列出mongodb数据库。使用db.createCollection()方法创建一个名为“catalog”的集合。随后,再次运行show dbs命令。
show dbs
db.createCollection("catalog")
show dbs
show dbs命令在创建“catalog”集合之前不列出“mongodb”数据库,但是在创建集合之后列出“mongodb”数据库,如图 5-9 所示。
图 5-9。
Creating a Database
用下面的命令列出mongodb数据库中的集合。
show collections
除了系统集合system.indexes之外,“目录”集合也被列出,如图 5-10 所示。
图 5-10。
Listing Collections
创建收藏
在上一节中,我们使用db.createCollection命令创建了一个名为“catalog”的集合。接下来,通过将capped选项字段设置为true,创建一个加盖的集合“catalog_capped”。capped 集合是一个固定大小的集合,它在添加和获取文档时跟踪插入顺序,因此提供了高吞吐量。
db.createCollection("catalog_capped", {capped: true, autoIndexId: true, size: 64 * 1024, max: 1000} )
如图 5-11 所示,创建了一个名为“catalog_capped”的加盖集合。
图 5-11。
Creating a Capped Collection
也可以使用db.runCommand命令创建一个集合。使用db.runCommand命令创建另一个名为“catalog_capped_2”的 capped 集合。
db.runCommand( { create: "catalog_capped_2", capped: true, size: 64 * 1024, max: 1000 } )
Capped 集合 catalog_capped_2 被创建,如图 5-12 所示。
图 5-12。
Creating a Capped Collection using db.runCommand()
创建文档
接下来,我们将向 MongoDB 集合添加文档。最初,catalog集合是空的。运行 mongo shell 方法db.<collection>.count()对catalog集合中的文档进行计数。将<collection>替换为收藏名称“catalog”。
db.catalog.count()
catalog集合中的文档数被列为 0,如图 5-13 所示。
图 5-13。
Finding Document Count
接下来,我们将向catalog集合添加一个文档。创建一个 JSON 文档结构,包含字段catalogId、journal、publisher、edition、title和author。
doc1 = {"catalogId" : "catalog1", "journal" : 'Oracle Magazine', "publisher" : 'Oracle Publishing', "edition" : 'November December 2013',"title" : 'Engineering as a Service',"author" : 'David A. Kelly'}
使用db.<collection>.insert()方法将文档添加到catalog集合中。
db.catalog.insert(doc1)
随后再次输出文档计数。
db.catalog.count()
来自db.catalog.insert()方法的输出,如图 5-14 所示,是一个类型为WriteResult的对象,其中nInserted为 1,这意味着增加了一个文档。文档计数被列为 1。
图 5-14。
Adding a Document
查找文档
db.collection.find(query, projection)方法用于查找文档。document类型的query参数使用查询操作符指定选择标准。类型为document的projection参数指定了要返回的字段。这两个参数都是可选的。要选择所有文档,请不要指定任何参数或指定空文档{}。例如,查找catalog集合中的所有文档。
db.catalog.find()
先前添加的一个文档被列为 JSON 文档,如图 5-15 所示。如果没有明确指定,_id字段会自动添加到文档中。
图 5-15。
Running a Query using find() Method
添加另一个文档
类似地,为另一个文档创建 JSON 结构。如果_id是唯一的,可以再次添加相同的文档。在 JSON 中包含_id字段作为显式字段/属性。_id字段值必须是类型为ObjectId的对象,而不是字符串文字。
doc2 = {"_id": ObjectId("507f191e810c19729de860ea"), "catalogId" : "catalog1", "journal" : 'Oracle Magazine', "publisher" : 'Oracle Publishing', "edition" : 'November December 2013',"title" : 'Engineering as a Service',"author" : 'David A. Kelly'};
使用db.<collection>.insert()方法添加文档。
db.catalog.insert(doc2)
如图 5-16 中的nInserted值 1 所示,另一个文档被添加到catalog集合中。
图 5-16。
Adding Another Document
随后使用db.<collection>.find()方法查询catalog集合。
db.catalog.find()
添加到catalog集合中的两个文档被列出,如图 5-17 所示。这两个文档在 JSON 中都有相同的名称/值对,除了_id字段,它有一个惟一的值。
图 5-17。
Running the find() Method
查询单个文档
db.<collection>.findOne()方法用于查找单个文档。从catalog集合中查找单个文档。
db.catalog.findOne()
其中一个文档通过查询得到输出,如图 5-18 所示。
图 5-18。
Using the findOne() Method
db.collection.findOne(query, projection)方法也接受两个类型都是document的参数,并且都是可选的。query参数指定查询选择标准,而projection参数指定要选择的字段。例如,选择edition、title和author字段,并将查询文档指定为{}。
db.catalog.findOne(
{ },
{ edition: 1, title: 1, author: 1 }
)
列出edition、title和author字段。_id字段总是由查询输出,如图 5-19 所示。
图 5-19。
Using a Query Projection
删除收藏
方法删除一个集合。例如,删除catalog集合。
db.catalog.drop()
随后,show collections方法不列出catalog集合,如图 5-20 所示。
图 5-20。
Dropping a Collection
添加一批文档
以前,我们一次添加一个文档。接下来,我们将添加一批文档。如果在前面的部分中还没有删除,则删除catalog集合。
db.catalog.drop()
使用db.catalog.insert()方法调用添加一个文档数组,其中doc1和doc2与前面相同。writeConcern选项指定了 MongoDB 提供的保证,值“majority”意味着insert()方法直到写入被传播到大多数节点后才返回。将ordered选项设置为true会按指定的顺序添加文件。
db.catalog.insert([doc1, doc2], { writeConcern: { w: "majority", wtimeout: 5000 }, ordered:true })
在前面的方法调用中使用了insert方法的完整语法,如下所示。
db.collection.insert(
<document or array of documents>,
{
writeConcern: <document>,
ordered: <boolean>
}
)
第一个参数是单个文档或文档数组。第二个参数是一个带有字段writeConcern和 ordered 的文档。writeConcern指定了写问题或 MongoDB 在插入成功时提供的保证。ordered参数设置为true,这意味着按照指定的顺序添加文档,如果其中一个文档出现错误,则不添加任何文档。如图 5-21 所示,增加的两个文件,输出中的nInserted为 2。
图 5-21。
Adding a Batch of Documents
运行db.catalog.find()方法查询catalog集合中的文档,如图 5-22 所示。
图 5-22。
Running the find() Method to list Documents added in a Batch
更新文档
db.collection.save()方法具有以下语法,如果文档已经存在,则更新文档,如果文档不存在,则发布新文档。
db.collection.save(
<document>,
{
writeConcern: <document>
}
)
文档由类型ObjectId的唯一_id标识。接下来,我们将把_id更新为ObjectId("507f191e810c19729de860ea")。创建一个更新的 JSON 文档,修改一些字段值。
doc1 = {"_id": ObjectId("507f191e810c19729de860ea"), "catalogId" : 'catalog1', "journal" : 'Oracle Magazine', "publisher" : 'Oracle Publishing', "edition" : '11-12-2013',"title" : 'Engineering as a Service',"author" : 'Kelly, David A.'}
使用catalog集合中的db.collection.save()方法保存文档。
db.catalog.save(doc1,{ writeConcern: { w: "majority", wtimeout: 5000 } })
通过更新现有文档来保存文档。返回的WriteResult对象中nMatched为 1、nUpserted为 0、nModified为 1,如图 5-23 所示。nUpserted字段指的是相对于修改现有文档而言添加的新文档的数量。
图 5-23。
Using the save() Method to Update a Document
使用find()方法查询catalog集合。
db.catalog.find()
更新后的文档被列为图 5-24 所示的文档之一。
图 5-24。
Querying Updated Document
将文档输出为 JSON
db.collection.find(query, projection)方法返回查询选择的文档上的光标。调用游标上的forEach(printjson)方法,以 JSON 格式输出文档。
db.catalog.find().forEach(printjson)
文件以 JSON 的形式输出,如图 5-25 所示。
图 5-25。
Outputting JSON
制作数据备份
mongodump实用程序用于创建数据库中数据的二进制导出。mongorestore实用程序与mongodump结合使用,从备份中恢复数据库。mongorestore实用程序要么创建一个新的数据库实例,要么添加到一个现有的数据库中。
运行下面的mongodump命令,将测试数据库导出到/data/backup目录。
mongodump --db test --out /data/backup
测试数据库被导出到/data/backup目录,如图 5-26 所示。
图 5-26。
Exporting the test Database
列出/data/backup目录中的目录。test数据库目录被列出,如图 5-27 所示。
图 5-27。
Listing the test Database
运行下面的mongorestore命令,将从/data/backup/test导出的数据恢复到testrestore数据库。
mongorestore --db testrestore /data/backup/test
/data/backup/test目录数据被恢复到testrestore数据库中,如图 5-28 所示。
图 5-28。
Restoring a Database
使用以下命令连接到 MongoDB shell。
mongo localhost:27017/testrestore
MongoDB shell 的启动如图 5-29 所示。
图 5-29。
Connecting to the Restored Database
使用以下命令列出数据库。
show dbs
当我们将备份恢复到testrestore数据库时,之前导出的mongodb数据库会被列出,如图 5-30 所示。
图 5-30。
Listing the Restored Database
将数据库名称设置为mongodb。
use mongodb
列出收藏。
show collections
查询catalog集合中的文档。
db.catalog.find()
前述命令的输出如图 5-31 所示。
图 5-31。
Listing and Querying the Restored Collection
删除文档
db.collection.remove方法用于删除文档,其语法如下。
db.collection.remove(
<query>,
<justOne>
)
例如,删除带有ObjectId("561ff033380a18f6587b0aa5")的文档。
db.catalog.remove({ _id: ObjectId("561ff033380a18f6587b0aa5") })
WriteResult中的nRemoved为 1,表示有一个文档被移除。在db.catalog.remove()方法调用前后运行db.catalog.find()方法。在调用db.catalog.remove()方法之前,先列出两个文档,之后只列出一个文档,如图 5-32 所示。
图 5-32。
Removing a Single Document
要删除所有文档,向db.catalog.remove()方法调用提供一个空文档{}。
db.catalog.remove({})
如图 5-33 所示nRemoved值为 2 表示多个文件被移除。
图 5-33。
Removing All Documents
必须为db.catalog.remove()方法调用提供一个空的查询文档。如果没有提供空文档{},则会产生一个错误,指示需要进行查询,如图 5-34 所示。
图 5-34。
An empty document must be provided to the remove() method to remove all documents
停止和重新启动 MongoDB 数据库
运行 MongoDB 实例的 Docker 容器可以用docker stop命令停止。
sudo docker stop mongo
用下面的命令列出正在运行的 Docker 容器。
sudo docker ps
用docker start命令再次启动 Docker 容器。
sudo docker start mongo
再次运行以下命令以列出正在运行的容器。
sudo docker ps
前述命令的输出如图 5-35 所示。停靠容器mongodb再次被列为正在运行。
图 5-35。
Listing a Docker Container after Restarting the Container
使用以下命令启动交互式终端,其中使用容器 ID 而不是容器名称。
sudo docker exec -it 68fe88ca79fe bash
在交互 shell 中用mongo命令启动 MongoDB shell,如图 5-36 所示。
图 5-36。
Starting the MongoDB Shell
将数据库设置为local并用show collections命令列出集合。随后将数据库设置为mongodb,并列出收藏。db.catalog.find()方法不列出任何文件,如图 5-37 所示。
图 5-37。
Listing Documents in the catalog Collection in local Database
退出 Mongo Shell
要退出交互终端,使用“exit”命令,并使用“exit”命令退出 MongoDB shell,也如图 5-38 所示。
图 5-38。
Exiting MongoDB Shell and TTY
摘要
在本章中,我们使用 MongoDB 的 Docker 映像在 Docker 容器中运行 MongoDB 实例。我们创建了一个数据库,将集合添加到数据库中,并将文档添加到集合中。我们还查询了 MongoDB 中的文档。我们演示了停止和启动 Docker 容器。我们还备份了一个 MongoDB 数据库,并随后从备份中恢复了数据库。在下一章,我们将讨论在 Docker 容器中运行另一个 NoSQL 数据库 Apache Cassandra。