Docker安装完毕,我们就可以试着来运行一些命令了,看看docker可以干什么。

一 Docker基本操作

1.1 创建一个容器

首先,让我们运行一个最简单的容器,hello-world。如果安装没有问题,并运行正确的话,应该会出现下面的结果:

$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
c04b14da8d14: Pull complete
Digest: sha256:0256e8a36e2070f7bf2d0b0763dbabdd67798512411de4cdcf9431a1feb60fd9
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker Hub account:
 https://hub.docker.com

For more examples and ideas, visit:
 https://docs.docker.com/engine/userguide/

可以看到,上述结果给了我们很多信息,首先,打印出了一条信息:Hello from Docker!
接着简单描述了一下产生该条信息所经历的一系列步骤:

1 Docker客户端连接到守护进程
2 Docker守护进程从Docker Hub拉取了hello-world镜像
3 Docker守护进程从该镜像创建了一个容器,来执行了命令并输出了我们当前看的这条消息
4 Docker守护进程将容器中的标准输出转发到你的终端。

需要补充一点的是,docker在运行一个容器时,首先会检查本地是否存在指定的镜像,如果有,则直接运行,如果没有,才会去Docker Hub上拉取。这也就是命令结果第一行为什么会显示Unable to find image 'hello-world:latest' locally的原因。

接下来,我们可以看一下目前所有的容器:

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS                    NAMES
1a058b3cde45        hello-world         "/hello"                 3 minutes ago       Exited (0) 3 minutes ago                            gigantic_austin

可以看到,只有一个我们刚才创建的hello-world容器,结果显示,该容器有一个ID1a058b3cde45 ,从hello-world镜像创建,执行的命令为/hello,当前状态为3分钟前已退出,最后还有个namegigantic_austin ,需要注意的是,这里的name看着很奇怪,因为它是随机生成的,后续我们可以看到如何自定义容器名称。

需要注意的是,如果你只运行docker ps,将看不到这个结果,因为它默认只显示正在运行的容器,而我们的hello-world运行完就立马退出了.
或者,你也可以运行docker ps -l用于查看最后创建的一个容器。

1.2 查看本地镜像:

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              c54a2cc56cbb        9 weeks ago         1.848 kB

docker images命令可以显示本机所有的Docker镜像。

1.3 在线查找镜像:

如果你不知道都有哪些可用的镜像,在线查找一下或许是个好注意:

直接使用docker search + [你想查找的镜像关键字],如:

$ docker search tomcat
NAME                        DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
tomcat                      Apache Tomcat is an open source implementa...   896       [OK]
dordoka/tomcat              Ubuntu 14.04, Oracle JDK 8 and Tomcat 8 ba...   22                   [OK]
consol/tomcat-7.0           Tomcat 7.0.57, 8080, "admin/admin"              16                   [OK]
consol/tomcat-8.0           Tomcat 8.0.15, 8080, "admin/admin"              15                   [OK]
davidcaste/alpine-tomcat    Apache Tomcat 7/8 using Oracle Java 7/8 wi...   10                   [OK]
cloudesire/tomcat           Tomcat server, 6/7/8                            9                    [OK]
...

结果会默认显示25条记录,通常第一条为官方镜像,即Docker Hub中的镜像。官方镜像会在OFFICIAL一列显示[OK]字样,另外,STARS一列的星星数量显示了该镜像的受欢迎程度,星星越多,表明用的人越多,不过为安全起见,通常建议首选官方镜像或自制镜像,而不是第三方的。

1.4 拉取镜像

使用docker pull [镜像名称[:版本]]可以拉取一个镜像:

注: 完整的镜像名称由[repository]/name:[tag]构成,[repository]为仓库,如果省略,则默认为library,即从Docker Hub拉取;如果省略tag,则默认拉取latest版本,name为镜像名称,不能省略。
$ docker pull tomcat:7
7: Pulling from library/tomcat
8ad8b3f87b37: Pull complete
751fe39c4d34: Pull complete
b165e84cccc1: Pull complete
65f65ec902a1: Pull complete
c7e29d14c31c: Pull complete
ae323d020901: Pull complete
f53151098775: Pull complete
4ee50529773d: Pull complete
e6cd9c8b5720: Pull complete
2274405e7ff7: Pull complete
ba48c8080acc: Pull complete
Digest: sha256:05749aa3217ba008878ff868de824602aaebcd6250c1510e489dbadb81ee37bd
Status: Downloaded newer image for tomcat:7

一个好的实践是,拉取镜像时,总是指定一个明确的版本,这样能确保在接下来的使用中,明确知道使用的是哪个版本。因为latest版本总是指向最新的版本,这将造成不确定性。

镜像拉取完成后,我们可以用它创建一个新的tomcat容器:

$ docker run -d --name tomcat001 -p 8081:8080 tomcat:7
72d39fb16383dc3ce667de4ea2c12b5c42d6cffdf818c6031fafe88fb6751f0a

其中,-d 指定容器在后台运行;--name用于指定容器的名称;-p 8081:8080 用于将容器内的8080端口映射到主机的8081端口,你也可以换成其他本机端口.如果需要,你可以创建多个容器使用,需要注意的是,本机映射的端口不能重复,name也不能重复。

查看当前容器:

$ docker ps -l
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
72d39fb16383        tomcat:7            "catalina.sh run"   3 minutes ago       Up 3 minutes        0.0.0.0:8081->8080/tcp   tomcat001

这时,我们就可以访问192.168.1.132:8081来查看运行的tomcat了,注意将IP替换成你的docker主机的IP。

1.5 查看容器日志

使用 docker logs 容器名称可以查看容器的日志输出,-f选项可以指定实时输出最新日志,类似于Linux 下的tail -f命令。

$ docker logs -f tomcat001
Sep 05, 2016 10:27:49 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: Server version:        Apache Tomcat/7.0.70
Sep 05, 2016 10:27:49 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: Server built:          Jun 15 2016 16:27:45 UTC
Sep 05, 2016 10:27:49 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: Server number:         7.0.70.0
Sep 05, 2016 10:27:49 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: OS Name:               Linux
Sep 05, 2016 10:27:49 AM 
...
...
INFO: Deployment of web application directory /usr/local/tomcat/webapps/ROOT has finished in 32 ms
Sep 05, 2016 10:27:49 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-apr-8080"]
Sep 05, 2016 10:27:49 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-apr-8009"]
Sep 05, 2016 10:27:49 AM org.apache.catalina.startup.Catalina start
INFO: Server startup in 655 ms

1.6 停止容器

$ docker stop tomcat001
tomcat001

1.7 启动容器

$ docker start tomcat001
tomcat001

1.8 删除容器

删除一个容器前,需要先停止容器,否则,需要使用 -f选项强制删除(不推荐)。
另外,如果容器包含数据卷的话,可以使用-v选项连同关联的数据卷一块删除,删除容器时,默认不删除数据卷,因为数据卷通常会包含我们的数据。

$ docker rm tomcat001
tomcat001

1.9 卷管理

到这里,似乎一切都在容器里,我们的应用好像还没怎么跟容器有联系。有多种方法可以运行我们的应用,最简单的就是将应用挂载为容器的一个数据卷,另外更常规的做法是直接把应用制作成一个镜像,方便后期的测试及发布等。容器存放数据的地方主要有两个,一个是数据卷,类似于Linux下挂载的文件夹;另一个是数据卷容器,即单独的用于存放数据的容器。关于容器的数据卷及数据卷容器的概念,还需要一篇文章讨论,在此就不做深入研究了。
最简单的使用数据卷的方式就是在创建一个容器时 增加-v选项,我们以一个最简单的Java web应用为例:

1 首先创建一个目录:

sudo mkdir -p /opt/data/myapp/ROOT
sudo chown -R $USER:root /opt/data/myapp

注意这里的$USER变量代表当前运行docker的用户,即安装docker时加入docker组的那个用户,其他用户可能会导致没权限。

2 在/opt/data/myapp/ROOT下创建一个WEB-INF目录:

$ mkdir /opt/data/myapp/ROOT/WEB-INF

3 新建一个web.xml:

vi /opt/data/myapp/ROOT/WEB-INF/web.xml

贴入以下内容,保存:

<?xml version="1.0" encoding="ISO-8859-1"?>

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  version="3.0"
  metadata-complete="true">

  <display-name>Welcome to Tomcat</display-name>
  <description>
     Welcome to Tomcat
  </description>

</web-app>

4 新建一个jsp页面:

vi /opt/data/myapp/ROOT/index.jsp

贴入以下内容,保存:

<!DOCTYPE html>
<html lang="en">
    </body>
        Hello, this is my first docker app!
    </body>
</html>

5 接下来,将我们的应用挂载到容器中:

$ docker run -d --name myapp -v /opt/data/myapp:/usr/local/tomcat/webapps -p 8888:8080 tomcat:7

6 访问 192.168.1.132:8888就可以了:

3001-docker.png

这种方式也是比较初级的用法,不过在本地开发及测试,还是挺方便的。在CI/CD工作流中,应该将应用直接制作为镜像。关于如何制作镜像,请参考后续文章。

1.10 删除镜像

删除一个镜像前,需要先停止使所有用它的容器,否则会报错,或者使用 -f选项强制删除。

$ docker rmi tomcat:7
Error response from daemon: conflict: unable to remove repository reference "tomcat:7" (must force) - container e1226ea69332 is using its referenced image c6c14b3960bd
$ docker rmi tomcat:7
Untagged: tomcat:7
Untagged: tomcat@sha256:05749aa3217ba008878ff868de824602aaebcd6250c1510e489dbadb81ee37bd
Deleted: sha256:967bcc6107b44f28ea76c4448da49d8d12328b39ee7dc48347e833b1d98df143
Deleted: sha256:d77369462cab111671c3797187b3b7473fc64a6039ec06a02af4376ac588ca5a
Deleted: sha256:33fcb0e88cc530b74d4081cb3e665000e829d05d5467a0a8a6fe6e9b4aa23ac8
Deleted: sha256:f08d7b065365610a76636083ac3edf85784ce764fb23f46304953d7e662846ac
Deleted: sha256:bc8a665ce1da8a10d642cb92864da7f5ca6d81483e20a8dfb5c06c2a1cc6473c
Deleted: sha256:3a2471d2c021fec5bc630486a8d5fa11a52068dfb4cf3589921775d6213bde2b
Deleted: sha256:0045842271a87e064b2e8d6b4a560b0eea7b415a80e4d70bb40d6ef247cdb949
Deleted: sha256:467e4252c9c86603b7c441b50a21b6ebd78f2ac6b0ab0236c3e0eb79c3d06e4e
Deleted: sha256:fc18fe11190c806227398f634be2865ae447ff677f052ffbbecea27241f961b1
Deleted: sha256:249266c821ee1779d332c7b7eb496be194109c4b0e99d3adcc4bd3d03cc1167e
Deleted: sha256:d7afd92fb07236c8a2045715a86b7d5f0066cef025018cd3ca9a45498c51d1d6
Deleted: sha256:9e63c5bce4585dd7038d830a1f1f4e44cb1a1515b00e620ac718e934b484c938

(完)


注: 本文原文最初发表在我的CSDN博客,现归档于此。
文章目录