docker 知识点汇总

什么是 Docker

Docker 简介

Docker 核心概念如下:

  1. Docker 引擎 (Docker Engine)
  2. Docker 客户端 (Docker Client)
  3. Docker 镜像 (Docker Images)
  4. Docker 容器 (Docker Containers)
  5. Docker 镜像注册中心 (Docker Registry)

Docker 的特点

  1. 快速运行

  2. 节省资源

    Docker 容器直接运行在 Docker 引擎之上,可直接利用宿主机硬件资源,无需占用过多的系统开销

  3. 便于交付

    Docker 的交付物是镜像,镜像不仅封装了程序,还包含了运行程序的环境

  4. 容易管理

    通过 Docker 客户端直接操作 Docker 引擎,非常方便的管理 Docker 镜像和容器

如何使用 Docker

镜像的常用操作

  1. 列出镜像

    [root@dev ~]# docker images
    REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
    centos latest ab9a80ab07d0 2 weeks ago 201.8 MB

    以上表格包含 5 个字段,其中

    • REPOSITORY 镜像仓库的名称
    • TAG 镜像的标签,一般带有版本或别名,这里的 lastest 表示最新版本
    • IMAGE ID 表示镜像的标识符,称为镜像 ID ,具备唯一性
    • created 表示镜像的创建时间
    • SIZE 大小
  2. 拉取镜像 docker pull

  3. 搜索镜像

    执行上面的命令,会输出带有 centos 关键字的镜像仓库。

    [root@dev ~]# docker search centos
    
    NAME                               DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
    centos The official build of CentOS. 5070 [OK]
    ansible/centos7-ansible Ansible on Centos7 119 [OK]
    jdeathe/centos-ssh CentOS-6 6.10 x86_64 / CentOS-7 7.5.1804 x... 104 [OK]
    consol/centos-xfce-vnc Centos container with "headless" VNC sessi... 73 [OK]
    imagine10255/centos6-lnmp-php56 centos6-lnmp-php56 48 [OK]
    centos/mysql-57-centos7 MySQL 5.7 SQL database server 45
    tutum/centos Simple CentOS docker image with SSH access 43
    gluster/gluster-centos Official GlusterFS Image [ CentOS-7 + Glu... 38 [OK]
    openshift/base-centos7 A Centos7 derived base image for Source-To... 37
    centos/postgresql-96-centos7 PostgreSQL is an advanced Object-Relationa... 36
    centos/python-35-centos7 Platform for building and running Python 3... 33
    kinogmt/centos-ssh CentOS with SSH 25 [OK]
    openshift/jenkins-2-centos7 A Centos7 based Jenkins v2.x image for use... 20
    centos/php-56-centos7 Platform for building and running PHP 5.6 ... 17
    pivotaldata/centos-gpdb-dev CentOS image for GPDB development. Tag nam... 10
    openshift/wildfly-101-centos7 A Centos7 based WildFly v10.1 image for us... 6
    openshift/jenkins-1-centos7 DEPRECATED: A Centos7 based Jenkins v1.x i... 4
    darksheer/centos Base Centos Image -- Updated hourly 3 [OK]
    pivotaldata/centos-mingw Using the mingw toolchain to cross-compile... 2
    pivotaldata/centos Base centos, freshened up a little with a ... 2
    blacklabelops/centos CentOS Base Image! Built and Updates Daily! 1 [OK]
    pivotaldata/centos-gcc-toolchain CentOS with a toolchain, but unaffiliated ... 1
    smartentry/centos centos with smartentry 0 [OK]
    pivotaldata/centos7-build CentosOS 7 image for GPDB compilation 0
    pivotaldata/centos7-test CentosOS 7 image for GPDB testing 0

    字段的意义如下

    1. NAME 表示镜像仓库的名称
      1. 不带 / 表示 Docker 官方发布的仓库
      2. 其他仓库表示个人仓库
    2. DESCRIPTION 表示镜像仓库描述
    3. STARS 表示镜像的收藏数,该数字体现该仓库的受欢迎程度
    4. OFFICAL 是否为官方仓库,官方仓库具有更高的安全性
    5. AUTOMATED 是否自动构建镜像仓库,用户可以将自己的 Docker Hub 绑定到 GitHub 或者 BitBucket 上,当代码提交后,可以自动构建镜像仓库
  4. 导出和导入镜像

    [root@dev docker]# docker save centos > centos.tar
    [root@dev docker]# docker load < centos.tar

当获取镜像后,就能基于镜像启动相应的容器。

容器的常用操作

  1. 创建并启动容器

    [root@dev docker]# docker run -i -t centos /bin/bash
    • -i 选项: 表示启动容器后,打开标准输入设备 (STDIN) ,可使用键盘进行输入
    • -t 选项: 表示启动容器后,分配一个伪终端,与服务器奖励一个会话
    • centos 参数: 表示需要运行的镜像名称,标准格式为 centos:latest ,若为 latest 版本,可以省略
    • /bin/bash 参数: 表示运行容器中的 bash 应用程序

    执行该命令后,会首先从本地拉取 centos 镜像,如果本地没有此镜像,就会从 docker hub 上拉取并存放在本地,随后就能根据镜像创建并启动 centos 容器。

    此时可以参考容器的命令提示符:

    [root@5b51855797e3 /]#

    其中

    • root 表示当前登录的用户名,默认都是以超级管理员身份登录的
    • 5b51855797e3 表示容器的标识符,一般称为 “容器 ID"
    • / 表示当前路径

    可在 # 符号后输入 Linux 命令,执行 exit 命令退出容器

  2. 列出容器

    [root@dev ~]# docker ps
    CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    5b51855797e3 centos "/bin/bash" 17 minutes ago Up 17 minutes sharp_mccarthy

    结果字段的具体意义如下

    1. CONTAINER ID 表示容器 ID
    2. IMAGE 镜像名称
    3. COMMAND 启动容器时运行的命令,Docker 要求在启动容器时需要运行一个命令
    4. CREATED 容器创建时间
    5. STAUS 表示容器运行的状态
      1. Up 表示运行中
      2. Existed 表示已退出
    6. PORTS 表示容器需要对外暴露的端口号
    7. NAMES 容器的名称

    docker ps 命令包括一些常用选项,描述如下

    • -a 列出所有的容器,包含所有的状态
    • -l 表示列出最近创建的容器,包括所有的状态
    • -n 表示列出 n 个 最近创建的容器,包括所有的状态
    • -q 表示仅仅列出 CONTAINER ID 字段
    • -s 表示在输出表格中增加一个 SIZE 字段
  3. 进入容器

    [root@dev ~]# docker ps
    CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    c6e7132314fd centos "/bin/bash" 2 minutes ago Up 2 minutes happy_colden
    [root@dev ~]# docker attach c6e7132314fd
    [root@c6e7132314fd /]#

    只能进入运行中的数据,不能进入已停止的数据。

  4. 执行命令

    使用以下命令像运行中的容器执行具体的命令

    [root@dev ~]# docker ps
    CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    e5fa12acb939 centos "/bin/bash" 20 seconds ago Up 19 seconds pensive_fermat
    [root@dev ~]# docker exec -i -t e5fa12acb939 ls -l
    total 56
    -rw-r--r-- 1 root root 12076 Dec 5 01:37 anaconda-post.log
    lrwxrwxrwx 1 root root 7 Dec 5 01:36 bin -> usr/bin
    drwxr-xr-x 5 root root 380 Dec 26 09:52 dev
    drwxr-xr-x 47 root root 4096 Dec 26 09:52 etc
    drwxr-xr-x 2 root root 4096 Apr 11 2018 home
    lrwxrwxrwx 1 root root 7 Dec 5 01:36 lib -> usr/lib
    lrwxrwxrwx 1 root root 9 Dec 5 01:36 lib64 -> usr/lib64
    drwxr-xr-x 2 root root 4096 Apr 11 2018 media
    drwxr-xr-x 2 root root 4096 Apr 11 2018 mnt
    drwxr-xr-x 2 root root 4096 Apr 11 2018 opt
    dr-xr-xr-x 192 root root 0 Dec 26 09:52 proc
    dr-xr-x--- 2 root root 4096 Dec 5 01:37 root
    drwxr-xr-x 11 root root 4096 Dec 5 01:37 run
    lrwxrwxrwx 1 root root 8 Dec 5 01:36 sbin -> usr/sbin
    drwxr-xr-x 2 root root 4096 Apr 11 2018 srv
    drwxr-xr-x 13 root root 0 Dec 26 09:45 sys
    drwxrwxrwt 7 root root 4096 Dec 5 01:37 tmp
    drwxr-xr-x 13 root root 4096 Dec 5 01:36 usr
    drwxr-xr-x 18 root root 4096 Dec 5 01:36 var
  5. 停止容器

    使用下面命令停止运行中的容器(需要指定 ID 或者容器名称):

     docker stop e5fa12acb939

    该命令会想容器发送 SIGTERM 信号,将等待很短的时间,再对容器发送 SIGKILL 信号,会立即终止容器。

  6. 终止容器

    docker kill e5fa12acb939
  7. 启动容器

    可以启动已经停止的容器

     docker start e5fa12acb939
  8. 重启容器

    docker restart e5fa12acb939
  9. 删除容器

    docker rm e5fa12acb939

    不能删除正在运行的容器,只能将它停止后,再删除。

  10. 导入和导出容器

    docker export e5fa12acb939 > centos.tar
    docker import foo.tar reycg/centos:latest

Docker 命令汇总

docker help

手工制作 java 镜像

整体步骤

  1. 容器启动前, 准备一个 JDK 压缩包,并存放在宿主机的 ~/software 目录下
  2. 容器启动时,通过数据卷的方式,将宿主机的 ~/software 目录挂载到容器的 /mnt/software 目录
  3. 容器启动后,先解压 JDK 压缩包,随后创建 JDK 符号链接
  4. 使用 docker commit 命令,提交当前容器为 reycg/java 的镜像
  5. 运行 reycg/java 镜像,启动一个 java 容器,并输出 java 版本号,从而验证镜像是否可用,最后自动删除当前容器

具体命令如下,前 3 个步骤

[root@dev software]# ls
jdk-8u121-linux-x64.tar.gz
[root@architecture01.general.dev.tj1 software]# docker run -i -t -v ~/software/:/mnt/software centos /bin/bash
[root@b3d2064d1a3d /]# ls
anaconda-post.log bin dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
[root@b3d2064d1a3d /]# ll /mnt/software/
total 178956
-rw-r--r-- 1 root root 183246769 Dec 26 12:41 jdk-8u121-linux-x64.tar.gz
[root@b3d2064d1a3d /]# tar -zxf /mnt/software/jdk-8u121-linux-x64.tar.gz -C /opt/
[root@b3d2064d1a3d /]# ll /opt/
total 4
drwxr-xr-x 8 10 143 4096 Dec 13 2016 jdk1.8.0_121
[root@b3d2064d1a3d /]# ln -s /opt/jdk1.8.0_121 /opt/jdk
[root@b3d2064d1a3d /]# ll /opt/jdk
lrwxrwxrwx 1 root root 17 Dec 26 12:44 /opt/jdk -> /opt/jdk1.8.0_121
[root@b3d2064d1a3d /]# /opt/jdk/bin/java -version
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

步骤 4, 5

[root@dev software]# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
reycg/java latest d3c1df69ffb2 13 seconds ago 571.9 MB
centos latest ab9a80ab07d0 2 weeks ago 201.8 MB
[root@dev software]# docker run --rm reycg/java /opt/jdk/bin/java -version
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

上面过程是手工完成的,除了这种方式,我们还可以写一段脚本,让其自动运行同样可以生成镜像,这就是下面讲的 Dockerfile。

使用 Dockerfile 制作镜像

Dockerfile 脚本文件,包括一些指令,通过学习这些指令,可以快速的编写镜像的构建脚本,从而让构建镜像做到自动化。下面先了解下 Docker file 的基本结构。

Dockerfile 的基本结构

  1. 设置基础镜像

    FROM centos:latest

    FROM 指令的值有固定的格式,即“仓库名:标签名”,若使用基础镜像的最新版本,则 latest 签名可以省略,否则需要指定基础镜像的具体版本。

  2. 设置维护者信息

    MAINTAINER "reycg"<reycg2017@163.com>

    MAINTAINER 指令没有固定格式,建议使用姓名与邮箱的格式,可以同时指定多个人

  3. 设置需要添加到容器中的文件

    ADD jdk-8u121-linux-x64.tar.gz /opt

    ADD 指令的第一个参数是宿主机的来源路径(可使用相对路径),第二个参数是容器的目标路径(必须为绝对路径)。

    ADD 指令还可以自动解压来源路径中的压缩包,将解压后的文件复制到目标路径中。

    除了 ADD 指令,还有一个类似的 COPY 指令,只是它只能完成简单的复制,而没有自动解压的功能。

  4. 设置镜像制作过程中需要执行的命令

    RUN ln -s /opt/jdk1.8.0_121 /opt/jdk

    使用 RUN 指令可以执行一系列构建镜像所需的命令,如果要执行多条命令,可以使用多行 RUN 命令,但最好是通过 \ 换行符合并成一条,这样能够减小所构建的镜像的体积。

  5. 设置容器启动时需要执行的命令

    CMD /opt/jdk/bin/java -version

    如果在使用 docker run 命令时指定了需要执行的命令,会覆盖 Dockerfile CMD 指令。

    在 Dockerfile 还有一个类似的 ENTRYPOINT 指令,只是后者所执行的指令不能被 docker run 覆盖。

了解了 Dockerfile 的基本结果后,后面我们使用 Dockerfile 构建一个 java 镜像。

使用 Dockerfile 构建镜像

将上一节的 Dockerfile 指令整理一下,得到汇总的文件内容:

FROM centos:latest
MAINTAINER "reycg"<reycg2017@163.com>
ADD jdk-8u121-linux-x64.tar.gz /opt
RUN ln -s /opt/jdk1.8.0_121 /opt/jdk
CMD /opt/jdk/bin/java -version

下面就使用 docker build 命令读取 Dockerfile 文件,并构建一个镜像:

[root@dev software]# docker build -t reycg/java .
Sending build context to Docker daemon 183.2 MB
Sending build context to Docker daemon
Step 0 : FROM centos:latest
---> ab9a80ab07d0
Step 1 : MAINTAINER "reycg"<reycg2017@163.com>
---> Running in ae37609d29d2
---> 51911673bc4a
Removing intermediate container ae37609d29d2
Step 2 : ADD jdk-8u121-linux-x64.tar.gz /opt
---> e4743bdb5bcd
Removing intermediate container 4ef5335f53e0
Step 3 : RUN ln -s /opt/jdk1.8.0_121 /opt/jdk
---> Running in 513ba2d0d2ff
---> 097586ce97cd
Removing intermediate container 513ba2d0d2ff
Step 4 : CMD /opt/jdk/bin/java -version
---> Running in cde9191ea078
---> cd4c35cfb8ac
Removing intermediate container cde9191ea078
Successfully built cd4c35cfb8ac

当执行成功后,将输出最终的镜像 ID (d3c1df69ffb2 ),此时可通过 docker images 查看最终生成的镜像

[root@dev software]# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
reycg/java latest cd4c35cfb8ac 27 minutes ago 571.9 MB
<none> <none> d3c1df69ffb2 56 minutes ago 571.9 MB
centos latest ab9a80ab07d0 2 weeks ago 201.8 MB

此时可使用 docker tag 命令来修改镜像的仓库名和标签名。

docker tag d3c1df69ffb2 reycg/java:1.0

此时再查看当前的镜像

[root@dev software]# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
reycg/java latest cd4c35cfb8ac 33 minutes ago 571.9 MB
reycg/java 1.0 d3c1df69ffb2 About an hour ago 571.9 MB

安装 jdk 后都需要设置一个 JAVA_HOME 和 PATH 环境变量,这样就可以在命令行中直接使用 Java 命令了。可以使用 ENV 指令来完成。

ENV JAVA_HOME /opt/jdk
ENV PATH $JAVA_HOME/bin:$PATH

这样完整的 Dockerfile 指令如下

FROM centos:latest
MAINTAINER "reycg"<reycg2017@163.com>
ADD jdk-8u121-linux-x64.tar.gz /opt
RUN ln -s /opt/jdk1.8.0_121 /opt/jdk
ENV JAVA_HOME /opt/jdk
ENV PATH $JAVA_HOME/bin:$PATH
CMD java -version

与 Spring Boot 整合

在微服务架构中,交付方式由应用程序转变为 Docker 镜像,将服务及其运行环境封装在 Docker 镜像中。若需要发布服务时,只需要根据镜像启动相应的容器即可。

搭建 Spring Boot 应用程序框架

标准的 Spring Boot 应用程序的 Maven 配置如下

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>demo.msa</groupId>
<artifactId>mesa-hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging> <name>mesa-hello</name>
<url>http://maven.apache.org</url> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.3.RELEASE</version>
</parent> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

由于使用了 spring-boot-maven-plugin 插件,在 mvn package 打包后将生成一个直接运行的 jar 包,生成的 jar 包默认文件名格式为 ${project.build.finalName} ,它是一个 maven 属性,相当于 ${project.artifactId}:${project.version}.

添加 Dockerfile

我们的应用是基于 Maven 构建的,Maven 规范要求我们将所有的资源放在 src/main/resources 资源目录下。 Dockerfile 也是资源文件,因此也需要放在该目录下。完整的文件内容如下:

FROM java
MAINTAINER "ReyCG"<reycg2017@163.com>
ADD mesa-hello-0.0.1-SNAPSHOT.jar app.jar
EXPOSE 8080
CMD java -jar app.jar

默认情况下, Spring Boot 开启的是 8080 端口,因此使用 ExPOSE 指令暴露出来。

最后使用 java -jar app.jar 执行 jar 包。

使用 Maven 构建 Docker 镜像

Dockerfile 创建成功了,下一步就是读取 Dockerfile,并构建 Docker 镜像。而这些则是由 spotfy 公司的 docker-maven-plugin 插件来完成的。具体 maven 配置如下:

  		<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.10</version>
<configuration>
<imageName>${project.groupId}/${project.artifactId}:${project.version}</imageName>
<dockerDirectory>${project.build.outputDirectory}</dockerDirectory>
<resources>
<resource>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>

下面来解释下 configuration 片段

  • imageName Docker 镜像名称,它由 ${project.groupId} 仓库名,${project.artifactId} 镜像名和 ${project.version} 标签名组成
  • dockerDirectory 指定 Dockerfile 文件所在的目录
  • resources/resource/directory 指定需要复制的根目录,其中 ${project.build.directory} 则表示 target 目录
  • resources/resource/directory 指定需要复制的文件

执行 mvn docker:build 即可编译镜像。编译成功后,查看一下

[tomcat@ root]$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
demo.msa/mesa-hello 0.0.1-SNAPSHOT 67b94db5ac60 About an hour ago 657 MB

启动 Spring Boot 的 Docker 容器

在后台运行容器,并将容器的 8080 端口绑定到宿主机 58080 端口上。

docker run -d -p 58080:8080 demo.msa/mesa-hello:0.0.1-SNAPSHOT

通过浏览器访问 localhost:8080 请求来验证下。

调整 Docker 内存限制

可以使用如下 Docker 命令监控 Docker 容器的运行情况

[tomcat@ root]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
eb8659f31ca3 demo.msa/mesa-hello:0.0.1-SNAPSHOT "/bin/sh -c 'java -j 37 minutes ago Up 37 minutes 0.0.0.0:58080->8080/tcp sharp_hodgkin
[tomcat@ root]$ docker stats eb8659f31ca3
CONTAINER CPU % MEM USAGE/LIMIT MEM % NET I/O
eb8659f31ca3 0.10% 540.2 MB/8.128 GB 6.65% 5.024 kB/7.208 kB

由此命令可以看出容器的 CPU 使用率,内存使用情况与使用率,网络 IO 使用情况等信息。

从内存使用情况来看,启动容器后默认分配了 8.128 GB 的内存,其中已经使用了 540.2 MB。由此我们可以估算出容器应用程序的最大内存,对启动容器所需分配的内存做出限制,可以节省更多的宿主机内容。从而可以启动更多的容器。

docker run 命令中添加 -m 参数就可以调整容器的内存限制。

[tomcat@ root]$ docker run -d -m 800m -p 58080:8081 demo.msa/mesa-hello:0.0.1-SNAPSHOT
40c7c49d0002c08c72034d97bb39d0b415df7a7eef0bfa959853649c88c8e77c
[tomcat@ root]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
40c7c49d0002 demo.msa/mesa-hello:0.0.1-SNAPSHOT "/bin/sh -c 'java -j 4 seconds ago Up 3 seconds 0.0.0.0:58080->8081/tcp dreamy_mcclintock
[tomcat@root]$ docker stats 40c7c49d0002
CONTAINER CPU % MEM USAGE/LIMIT MEM % NET I/O
40c7c49d0002 105.87% 531.8 MB/838.9 MB 63.39% 468 B/558 B

问题记录

  1. centos 6 如何安装 docker

    https://www.liquidweb.com/kb/how-to-install-docker-on-centos-6/

  2. docker 不能连接问题

    Get http:///var/run/docker.sock/v1.19/images/json: dial unix /var/run/docker.sock: no such file or directory. Are you trying to connect to a TLS-enabled daemon without TLS?
    
    

    解决方案 http://www.cnblogs.com/ashinliu/p/5477259.html

    http://tinylab.org/use-docker-without-sudo/

参考

  1. 《架构探险—轻量级微服务架构》
  2. https://www.liquidweb.com/kb/how-to-install-docker-on-centos-6/
  3. http://www.cnblogs.com/ashinliu/p/5477259.html
上一篇:CUBRID学习笔记 8 复制数据库


下一篇:Docker 资源汇总