Docker 属于 Linux 容器的一种封装,它是目前最流行的容器解决方案。容器有点像虚拟机,提供虚拟化的环境。Docker 本身并不是容器,它是创建容器的工具,是应用容器引擎。
Build, Ship and Run. Build once,Run anywhere.
Docker 的主要用途,目前有三大类:
在 Docker 中,有两大核心概念 image(镜像)和 container(容器)。Docker 把应用程序及其依赖打包在 image 文件里面。只有通过这个文件,才能生成 container。
我们以编程语言中的类和实例的关系来类比 image 和 container。其中 image 好比一个 Class 类文件,container 就是类的实例,image 是创建 container 的模板,image 可以“继承”自其他 image 文件,每个 container 容器都是由一个 image 生成,同一个 image 文件,可以生成多个同时运行的 container 实例。
image 镜像生成的 conatiner 实例,本身也是一个文件,称为容器文件。所以一旦容器生成,就会同时存在两个文件:image 文件和 container 文件。关闭容器并不会删除容器文件,只是容器停止运行而已。
Docker 和传统虚拟化方式区别:传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。
Docker 跟传统的虚拟化方式相比具有众多的优势:
Docker 使用客户端-服务器 (C/S) 架构模式,使用远程 API 来管理和创建 Docker 容器。通过 docker version
命令查看可以看到 docker 包含一个客户端和服务端的程序:
Client: Docker Engine - Community
Version: 19.03.1
API version: 1.40
Go version: go1.12.5
Git commit: 74b1e89
Built: Thu Jul 25 21:21:07 2019
OS/Arch: linux/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 19.03.1
API version: 1.40 (minimum version 1.12)
Go version: go1.12.5
Git commit: 74b1e89
Built: Thu Jul 25 21:19:36 2019
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.2.6
GitCommit: 894b81a4b802e4eb2a91d1ce216b8817763c29fb
runc:
Version: 1.0.0-rc8
GitCommit: 425e105d5a03fabd737a126ad93d62a9eeede87f
docker-init:
Version: 0.18.0
GitCommit: fec3683
Docker 引擎是一个包含以下主要组件的客户端服务器应用程序:
标题 | 说明 |
---|---|
镜像(Images) | Docker 镜像是用于创建 Docker 容器的模板。 |
容器(Container) | 容器是独立运行的一个或一组应用。 |
客户端(Client) | Docker 客户端通过命令行或者其他工具使用 Docker API 与 Docker 的守护进程通信。 |
主机(Host) | 一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。 |
仓库(Registry) | Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。 |
Docker Machine | Docker Machine 是一个简化 Docker 安装的命令行工具。 |
Docker 命令分管理命令 Management Commands
和命令 Commands
。Docker 1.13+ 引入了管理命令来帮助组织一堆 Docker 命令。两个命令都做同样的事情,管理命令有助于对所有命令进行分类,并使命令本身更加一致。所以推荐使用管理命令,虽然多敲了几个字符,但是语义更清晰。
docker images # 查看现有镜像
docker image ls # 查看现有镜像,和上面等同
# docker image ls -f dangling=true # 查看虚悬镜像,-f 即 --filter,过滤镜像
docker image pull [imageName] # 拉取镜像
docker image rm [imageName] # 删除镜像,等同 docker rmi
docker image prune # 删除虚悬镜像
docker container ls [-a] # 列出正在运行的容器,等同于 docker ps,-a 可查看所有容器
docker container run [hello-world] # 运行容器
docker container exec [containerID] # 进入容器内部
docker container start # 启动已经生成、已经停止运行的容器文件
docker container stop [containerID] # 终止容器运行
docker container kill [containID] # 手动杀死终止容器运行
docker container rm [containerID] # 删除容器,等同 docker rm
docker container logs [containerID] # 查看 docker 容器的输出
docker container cp [containID]:[/path/to/file] . # 从正在运行的 Docker 容器里面,将文件拷贝到本机
docker container prune # 删除所有停止运行的容器
docker rmi `docker images -q` # 直接删除所有镜像
docker rm `docker ps -aq` # 直接删除所有容器
docker rmi `docker images | grep xxxxx | awk '{print $3}'` # 按条件筛选之后删除镜像
docker rm `docker ps -a | grep xxxxx | awk '{print $1}'` # 按条件筛选之后删除容器
docker ps [-a] # 查看所有正在运行的容器,-a 可查看所有容器
docker stop [containerID] # 终止容器运行
docker system df # 查看镜像、容器、数据卷所占用的空间
docker volume ls # 查看数据卷
docker volume prune # 删除无主数据卷
docker inspect [containerID] # 查看容器状态
示例:
docker rum -it --rm [imageName] bash # 以交互方式启动容器,停止后自动移除
docker exec -it [containerID] bash # 以交互方式进入容器
需要注意:
docker container run
命令具有自动抓取 image 文件的功能。如果发现本地没有指定的 image 文件,就会从仓库自动抓取。因此,前面的 docker image pull
命令并不是必需的步骤。docker container run
是新建容器,每运行一次生成一个容器文件,注意要避免重复执行。可以使用 docker container start
启动已生成的容器。docker container kill
向容器内主进程发出 SIGKILL 信号来终止容器运行。docker container stop
先向主进程发出 SIGTERM 信号,然后过一段时间再发出 SIGKILL 信号。这两个信号的差别是,应用程序收到 SIGTERM 信号以后,可以自行进行收尾清理工作,但也可以不理会这个信号。如果收到 SIGKILL 信号,就会强行立即终止,那些正在进行中的操作会全部丢失。docker container logs
查看 docker 容器的输出,即容器里面 Shell 的标准输出。如果 docker run
命令运行容器的时候,没有使用 -it参数
,就要用这个命令查看输出。docker container exec
进入容器内部。如果 docker run
命令运行容器的时候,没有使用 -it参数
,就要用这个命令进入容器内部。# 查看日志
$ docker logs [OPTIONS] CONTAINER
Options:
--details 显示更多的信息
-f, --follow 跟踪实时日志
--since string 显示自某个timestamp之后的日志,或相对时间,如42m(即42分钟)
--tail string 从日志末尾显示多少行日志, 默认是all
-t, --timestamps 显示时间戳
--until string 显示自某个timestamp之前的日志,或相对时间,如42m(即42分钟)
# 查看指定时间后的日志,只显示最后100行
docker logs -f -t --since="2018-02-08" --tail=100 [containID]
# 查看最近30分钟的日志
docker logs --since 30m [containID]
# 查看某时间之后的日志
docker logs -t --since="2018-02-08T13:23:37" [containID]
# 查看某时间段日志
docker logs -t --since="2018-02-08T13:23:37" --until "2018-02-09T12:23:37" [containID]
Dockerfile 文件是一个文本文件,用于配置 image,生成自己的 image 镜像。在配置 Dockerfile 文件之前,需要先添加一个文本文件 .dockerignore
,用于排除不需要打包进入 image 镜像的文件路径。
.git
node_modules
npm-debug.log
之后创建 Dockerfile 文本文件,配置如下(摘取自阮一峰博客 Docker 入门教程):
FROM node:8.4 // 该 image 镜像继承官方 node 8.4 版本的 image
MAINTAINER nicestar // 标明作者
COPY . /app // 将除 .dockerignore 排除文件外的所有文件 copy 到 /app 目录
WORKDIR /app // 指定接下来的工作目录为 /app
RUN npm install // 安装依赖,安装后的所有依赖都将打包到 image 文件
EXPOSE 3000 // 暴露 3000 端口,允许外部连接这个端口
配置好 Dockerfile 文件之后,即可创建自己的 image 镜像文件:
# docker image build -t [username]/[repository]:[tag] .
docker image build -t koa-demo:0.0.1 .
参数详解: -t
用来指定 image 文件的名字,名字后面冒号指定标签,如果不指定默认的标签为 latest
。最后的参数指定 Dockerfile 文件所在的路径,上例中 Dockerfile 在当前路径,所以为点号 .
。
docker container run --rm -p 8000:3000 -it koa-demo:0.0.1 /bin/bash
参数详解:
--rm 参数
:容器停止运行时自动删除容器文件-p 参数
:容器的 3000 端口映射到本机的 8000 端口。-it 参数
:容器的 Shell 映射到当前的 Shell,然后你在本机窗口输入的命令,就会传入容器。koa-demo:0.0.1
:image 文件的名字(如果有标签,还需要提供标签,默认是 latest 标签)。/bin/bash
:附加命令,容器启动以后,内部第一个执行的命令。这里是启动 Bash,保证用户可以使用 Shell。上例容器启动之后,需要手动在命令窗口执行 node index.js
来运行服务,通过 CMD 命令
可以自动执行。我们在 Dockerfile 里添加:
FROM node:8.4 // 该 image 镜像继承官方 node 8.4 版本的 image
MAINTAINER nicestar // 标明作者
COPY . /app // 将除 .dockerignore 排除文件外的所有文件 copy 到 /app 目录
WORKDIR /app // 指定接下来的工作目录为 /app
RUN npm install // 安装依赖,安装后的所有依赖都将打包到 image 文件
EXPOSE 3000 // 暴露 3000 端口,允许外部连接这个端口
CMD node demos/01.js // 容器启动后自动执行
需要注意:添加了 CMD 命令
后,启动容器时后面便不能附加命令 /bin/bash
了,否则会覆盖 CMD 命令
。
RUN 命令
与 CMD 命令
的区别:
RUN 命令
在 image 文件的构建阶段执行,执行结果都会打包进入 image 文件;CMD 命令
则是在容器启动后执行。RUN 命令
,但是只能有一个 CMD 命令
。docker login
# docker image tag [imageName] [username]/[repository]:[tag]
docker image tag koa-demos:0.0.1 nicestar/koa-demos:0.0.1
docker image push [username]/[repository]:[tag]
可以在创建 image 镜像或者发布 image 镜像时标注用户名。
ENTRYPOINT 与 CMD 的关系:
sudo chmod 666 /var/run/docker.sock
build.sh:
#!/usr/bin/env bash
./mvnw clean package -Dmaven.test.skip=true
docker build -t docker.tgnb.cc/live/api-service:2.8.4 .
docker push docker.tgnb.cc/live/api-service:2.8.4
Dockerfile
FROM openjdk:8-jre
MAINTAINER tg tg@gmail.com
COPY api/target/api-1.0.RELEASE.jar /api-service.jar
ENTRYPOINT ["java","-jar","/api-service.jar", "-Xms6.5g", "-Xmx6.5g","-xx:NewSize=5.5g","-xx:MaxNewSize=5.5g","-XX:MaxDirectMemorySize=1g"]
systemctl daemon-reload
service docker restart
service docker status
报错:
Nicestar-mysql | 2019-09-02T08:07:06.346042Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
Nicestar-mysql | 2019-09-02T08:07:06.350661Z 0 [Warning] Setting lower_case_table_names=2 because file system for /var/lib/mysql/ is case insensitive
Nicestar-mysql | 2019-09-02T08:07:06.467170Z 0 [ERROR] InnoDB: Operating system error number 95 in a file operation.
Nicestar-mysql | 2019-09-02T08:07:06.467192Z 0 [ERROR] InnoDB: Error number 95 means 'Operation not supported'
Nicestar-mysql | 2019-09-02T08:07:06.467201Z 0 [ERROR] InnoDB: File ./ib_logfile101: 'Linux aio' returned OS error 195. Cannot continue operation
Nicestar-mysql | 2019-09-02T08:07:06.467206Z 0 [ERROR] InnoDB: Cannot continue operation.
首先在 docker-compose.yml
添加配置文件:
volumes:
- ./mysql/conf:/etc/mysql/conf.d
在 ./mysql/conf
文件夹下添加一个本地配置文件 local.cnf
:
[mysqld]
innodb_use_native_aio=0
给文件授权:
sudo chmod 400 local.cnf
重新启动,问题解决!
docker-compose -f docker-compose-dev.yml up
报错:
denied: requested access to the resource is denied
需要修改 tag,然后再推送:
# 修改 tag
docker tag spring-mybatis:0.0.1 nicestar/spring-mybatis:0.0.1
# 推送镜像
docker push nicestar/spring-mybatis:0.0.1
docker push 时报错:
denied: requested access to the resource is denied
解决方式:删除客户端配置文件 ~/.docker/config.json
,然后在登录 docker 后即可推送成功。
Linux 执行.sh 文件,提示 No such file or directory
的问题,可能是平台之间权限兼容的问题。
首先用 vim 打开该 sh 文件,输入 :set ff
,回车显示文件编码为 fileformat=dos
。所以需要重新设置下脚本文件格式,vim 输入 :set ff=unix
,保存后退出再执行即可。
需要注意:使用 vagrant 虚拟机进行 maven 打包的时候,需要配置 mvnw 文件编码。
docker 登录报错, x509: certificate signed by unknown authority.
:
docker login -u admin -p xxx https://docker.xx.cc
Note: If the command docker-compose fails after installation, check your path. You can also create a symbolic link to /usr/bin or any other directory in your path.
For example:
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
Install Compose on Linux systems
新增或编辑 /etc/docker/daemon.json
文件:
{
"insecure-registries": ["docker.tgnb.cc"]
}
重启 docker:
sudo service docker restart