什么是 Docker
Docker 简介
Docker 核心概念如下:
- Docker 引擎 (Docker Engine)
- Docker 客户端 (Docker Client)
- Docker 镜像 (Docker Images)
- Docker 容器 (Docker Containers)
- Docker 镜像注册中心 (Docker Registry)
Docker 的特点
快速运行
-
节省资源
Docker 容器直接运行在 Docker 引擎之上,可直接利用宿主机硬件资源,无需占用过多的系统开销
-
便于交付
Docker 的交付物是镜像,镜像不仅封装了程序,还包含了运行程序的环境
-
容易管理
通过 Docker 客户端直接操作 Docker 引擎,非常方便的管理 Docker 镜像和容器
如何使用 Docker
镜像的常用操作
-
列出镜像
[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
大小
-
拉取镜像
docker pull
-
搜索镜像
执行上面的命令,会输出带有 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字段的意义如下
-
NAME
表示镜像仓库的名称- 不带
/
表示 Docker 官方发布的仓库 - 其他仓库表示个人仓库
- 不带
-
DESCRIPTION
表示镜像仓库描述 -
STARS
表示镜像的收藏数,该数字体现该仓库的受欢迎程度 -
OFFICAL
是否为官方仓库,官方仓库具有更高的安全性 -
AUTOMATED
是否自动构建镜像仓库,用户可以将自己的 Docker Hub 绑定到 GitHub 或者 BitBucket 上,当代码提交后,可以自动构建镜像仓库
-
-
导出和导入镜像
[root@dev docker]# docker save centos > centos.tar
[root@dev docker]# docker load < centos.tar
当获取镜像后,就能基于镜像启动相应的容器。
容器的常用操作
-
创建并启动容器
[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
命令退出容器 -
-
列出容器
[root@dev ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5b51855797e3 centos "/bin/bash" 17 minutes ago Up 17 minutes sharp_mccarthy结果字段的具体意义如下
-
CONTAINER ID
表示容器 ID -
IMAGE
镜像名称 -
COMMAND
启动容器时运行的命令,Docker 要求在启动容器时需要运行一个命令 -
CREATED
容器创建时间 -
STAUS
表示容器运行的状态-
Up
表示运行中 -
Existed
表示已退出
-
-
PORTS
表示容器需要对外暴露的端口号 -
NAMES
容器的名称
docker ps
命令包括一些常用选项,描述如下-
-a
列出所有的容器,包含所有的状态 -
-l
表示列出最近创建的容器,包括所有的状态 -
-n
表示列出 n 个 最近创建的容器,包括所有的状态 -
-q
表示仅仅列出 CONTAINER ID 字段 -
-s
表示在输出表格中增加一个 SIZE 字段
-
-
进入容器
[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 /]#只能进入运行中的数据,不能进入已停止的数据。
-
执行命令
使用以下命令像运行中的容器执行具体的命令
[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 -
停止容器
使用下面命令停止运行中的容器(需要指定 ID 或者容器名称):
docker stop e5fa12acb939
该命令会想容器发送 SIGTERM 信号,将等待很短的时间,再对容器发送 SIGKILL 信号,会立即终止容器。
-
终止容器
docker kill e5fa12acb939
-
启动容器
可以启动已经停止的容器
docker start e5fa12acb939
-
重启容器
docker restart e5fa12acb939
-
删除容器
docker rm e5fa12acb939
不能删除正在运行的容器,只能将它停止后,再删除。
-
导入和导出容器
docker export e5fa12acb939 > centos.tar
docker import foo.tar reycg/centos:latest
Docker 命令汇总
docker help
手工制作 java 镜像
整体步骤
- 容器启动前, 准备一个 JDK 压缩包,并存放在宿主机的
~/software
目录下 - 容器启动时,通过数据卷的方式,将宿主机的
~/software
目录挂载到容器的/mnt/software
目录 - 容器启动后,先解压 JDK 压缩包,随后创建 JDK 符号链接
- 使用
docker commit
命令,提交当前容器为reycg/java
的镜像 - 运行
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 的基本结构
-
设置基础镜像
FROM centos:latest
FROM
指令的值有固定的格式,即“仓库名:标签名”,若使用基础镜像的最新版本,则latest
签名可以省略,否则需要指定基础镜像的具体版本。 -
设置维护者信息
MAINTAINER "reycg"<reycg2017@163.com>
MAINTAINER
指令没有固定格式,建议使用姓名与邮箱的格式,可以同时指定多个人 -
设置需要添加到容器中的文件
ADD jdk-8u121-linux-x64.tar.gz /opt
ADD
指令的第一个参数是宿主机的来源路径(可使用相对路径),第二个参数是容器的目标路径(必须为绝对路径)。ADD
指令还可以自动解压来源路径中的压缩包,将解压后的文件复制到目标路径中。除了
ADD
指令,还有一个类似的COPY
指令,只是它只能完成简单的复制,而没有自动解压的功能。 -
设置镜像制作过程中需要执行的命令
RUN ln -s /opt/jdk1.8.0_121 /opt/jdk
使用
RUN
指令可以执行一系列构建镜像所需的命令,如果要执行多条命令,可以使用多行RUN
命令,但最好是通过\
换行符合并成一条,这样能够减小所构建的镜像的体积。 -
设置容器启动时需要执行的命令
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
问题记录
-
centos 6 如何安装 docker
https://www.liquidweb.com/kb/how-to-install-docker-on-centos-6/
-
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?