docker入门和实践
# Docker介绍
Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。
# Docker 架构
Docker 包括三个基本概念:
镜像(Image):Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。
容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像。
Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。
Docker 容器通过 Docker 镜像来创建。
容器与镜像的关系类似于面向对象编程中的对象与类。
Docker | 面向对象 |
---|---|
容器 | 对象 |
镜像 | 类 |
概念 | 说明 |
---|---|
Docker 镜像(Images) | Docker 镜像是用于创建 Docker 容器的模板,比如 Ubuntu 系统 |
Docker 容器(Container) | 容器是独立运行的一个或一组应用,是镜像运行时的实体 |
Docker 客户端(Client) | Docker 客户端通过命令行或者其他工具使用 Docker SDK (https://docs.docker.com/develop/sdk/) 与 Docker 的守护进程通信 |
Docker 主机(Host) | 一个物理或者虚拟的机器用于执行 Docker 守护进程和容器 |
Docker Registry | Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库 |
Docker Hub (opens new window) 提供了庞大的镜像集合供使用。
# Docker的安装
Docker安装要根据不同环境,支持Linux、Windows、MacOS等平台,按照参考文档一步步配置即可:
CentOS | Debian | Fedora | Ubuntu安装Docker参考:Docker官方文档 (opens new window)
Kali安装Docker参考:Kali官网文档 (opens new window)
Windows安装参考:Docker官方文档 (opens new window)
MacOS安装参考:Docker官方文档 (opens new window)
国内的菜鸟教程网站:Docker安装文档 (opens new window)
国内的道客云网站:Docker安装文档 (opens new window)
注意区分Docker的不同版本:
Docker-ce / Docker-ee:当前的Docker分为社区版/企业版,由Docker官方维护,版本命名规则改为基于时间:YY.MM,如Docker version 20.10.6
Docker.io (Docker-io) / Docker-engine / Docker:Docker的早期版本,早期时由Docker官方维护,版本号更新到Docker version 1.13.1,而后Docker官方维护的版本更新为Docker-ce / Docker-ee,而Docker.io继续由Debian / Ubuntu团队维护,期间1年多时间没有对其更新,直到2019年8月恢复,至今一直正常更新维护,所以网上有些文章说Docker.io是旧的版本并不完全准确 通过以下命令可以查看Docker版本以及Docker运行相关信息:
# 查看Docker版本
docker -v
docker --version
docker version
# 查看Docker运行相关信息
docker info
2
3
4
5
6
7
8
# Docker镜像加速
国内从 DockerHub 拉取镜像有时会遇到困难,此时可以配置镜像加速器。Docker 官方和国内很多云服务商都提供了国内加速器服务,例如: 科大镜像:https://docker.mirrors.ustc.edu.cn/ 网易:https://hub-mirror.c.163.com/ 阿里云:https://你的ID.mirror.aliyuncs.com 七牛云加速器:https://reg-mirror.qiniu.com
Ubuntu14.04、Debian7Wheezy 对于使用 upstart 的系统而言,编辑 /etc/default/docker 文件,在其中的 DOCKER_OPTS 中配置加速器地址:
DOCKER_OPTS="--registry-mirror=https://registry.docker-cn.com"
重新启动服务:
sudo service docker restart
Ubuntu16.04+、Debian8+、CentOS7 对于使用 systemd 的系统,请在 /etc/docker/daemon.json 中写入如下内容(如果文件不存在请新建该文件):
{"registry-mirrors":["https://reg-mirror.qiniu.com/"]}
重新启动服务:
sudo systemctl daemon-reload
sudo systemctl restart docker
2
# 快速开始
Docker命令的使用方法可以用docker --help/-h或docker COMMAND --help/-h查看,常用命令总结如下
# 删除旧版本
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 安装新的版本
sudo yum install -y yum-utils
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin
sudo systemctl start docker
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 镜像管理
从Docker Hub (opens new window)查找镜像: (也可以直接去官方仓库查找,这样信息更直观完整)
docker search [OPTIONS] TERM
# OPTIONS:
# -f,--filter <filter>:列出收藏数不小于指定值的镜像
# filter包括stars=100(收藏数不少于100的镜像),is-official=true(指定Docker官方发布的镜像)
# --limit <num>:设置最多输出num条记录,默认25条
# --no-trunc:不截断,显示完整的镜像描述
eg:
# 从Docker Hub搜索收藏数多于100的官方node镜像
docker search -f "is-official=true" node
docker search -f stars=100 node
2
3
4
5
6
7
8
9
10
从镜像仓库拉取镜像:(拉取的镜像元信息存储在 /var/lib/docker/ 目录下)
docker pull [OPTIONS] NAME[:TAG]
# OPTIONS:
# -a:拉取所有TAG镜像
# --disable-content-trust:忽略镜像的校验,默认开启
eg:
# 从Docker Hub下载node最新版镜像
docker pull node
2
3
4
5
6
7
8
列出本地镜像:
docker images [OPTIONS] [REPOSITORY[:TAG]]
# OPTIONS:
# -a:列出本地所有的镜像,包括中间映像层
# -q,--quiet:只显示镜像ID
# --digests:显示镜像的摘要信息
# --no-trunc:不截断,显示完整的镜像信息
2
3
4
5
6
7
删除本地镜像:
docker rmi [OPTIONS] IMAGE [IMAGE...]
# OPTIONS:
# -f,--force:强制删除
2
3
4
标记本地镜像,将其归入某一仓库:
docker tag IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]
eg:
# 将镜像ubuntu:latest标记为captain_rb/ubuntu:v3镜像
docker tag ubuntu:latest captain_rb/ubuntu:v3
2
3
4
5
从本地容器创建一个新的镜像:
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
# OPTIONS:
# -a,--author <author>:提交的镜像作者
# -c,--change <list>:使用Dockerfile指令来创建镜像
# -m,--message <string>:提交时的说明信息
# -p,--pause:在commit时将容器暂停
2
3
4
5
6
7
将一个或多个镜像打包:
docker save [OPTIONS] IMAGE [IMAGE...]
# OPTIONS:
# -o,--output <atchive>:将镜像打包为tar包
//将镜像库中的postgres和mongo打包
docker save -o /root/images.tar postgres:9.6 mongo:3.4
docker save busybox > busybox.tar
//gzip 保存映像文件
docker save myimage:latest | gzip > myimage_latest.tar.gz
2
3
4
5
6
7
8
9
从tar包加载镜像:(可用于离线安装)
docker load [OPTIONS]
# OPTIONS:
# -i,--input <atchive>:从tar包加载镜像
# -q,--quiet:压缩输出信息
//postgres:9.6和mongo:3.4载入进来
docker load -i images.tar
docker load < images.tar.gz
2
3
4
5
6
7
8
9
使用Dockerfile创建镜像:
docker build [OPTIONS] PATH | URL
# OPTIONS:
# -f,--file <path>:指定要使用的Dockerfile路径
# -t,--tag <list>:镜像名字及标签,通常为 name:tag 或者 name 格式
# -q,--quiet:安静模式,成功后只输出镜像 ID
# --rm:设置镜像成功后删除中间容器
eg:
# 在当前目录下构建名为captain_rb/myapp:v1的镜像
docker build -t captain_rb/myapp:v1 .
2
3
4
5
6
7
8
9
# 容器管理
创建一个新的容器并启动,运行命令:
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
# OPTIONS:
# -d:后台运行容器,并返回容器ID
# -i:以交互模式运行容器,通常与-t同时使用
# -t:为容器重新分配一个伪输入终端
# -p:指定端口映射,格式为:"主机端口:容器端口"
# -P:随机端口映射,容器内部端口随机映射到主机的端口
# -v,--volume:指定卷的映射,格式为:"主机卷:容器卷"
# --name="new name":为容器指定一个名称
# --dns 8.8.8.8:指定容器使用的DNS服务器,默认和宿主一致
eg:
docker run -it nginx:latest /bin/bash
docker run -p 80:80 -v /data:/data -d nginx:latest
2
3
4
5
6
7
8
9
10
11
12
13
创建一个新的容器,不启动:
docker create [OPTIONS] IMAGE [COMMAND] [ARG...]
# OPTIONS 同上
2
在运行的容器中执行命令:
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
# OPTIONS:
# -d:后台运行
# -i:以交互模式执行命令,通常与-t同时使用
# -t:分配一个伪终端
eg:
# 进入正在运行的nginx容器
docker exec -it nginx /bin/bash
2
3
4
5
6
7
8
启动/停止/重启 容器:
docker start CONTAINER [CONTAINER...]
docker stop CONTAINER [CONTAINER...]
docker restart CONTAINER [CONTAINER...]
2
3
获取容器/镜像的元数据:
docker inspect NAME|ID [NAME|ID...]
列出本地容器:
docker ps [OPTIONS]
# OPTIONS:
# -a:显示所有的容器,包括未运行的
# -f:根据条件过滤显示的内容
# -l:显示最近创建的容器
# -n:列出最近创建的n个容器
# -q:静默模式,只显示容器ID
# -s:显示总的文件大小
# --no-trunc:不截断,输出容器详细信息
2
3
4
5
6
7
8
9
杀掉运行中的容器:
docker kill [OPTIONS] CONTAINER [CONTAINER...]
# OPTIONS:
# -s,--signal:向容器发送一个信号
2
3
删除容器:
docker rm [OPTIONS] CONTAINER [CONTAINER...]
# OPTIONS:
# -f:通过 SIGKILL 信号强制删除一个运行中的容器
# -l:移除容器间的网络连接,而非容器本身
# -v:删除与容器关联的卷
2
3
4
5
暂停/恢复容器运行:
docker pause CONTAINER [CONTAINER...]
docker unpause CONTAINER [CONTAINER...]
2
查看容器中运行的进程信息:
docker top [OPTIONS] CONTAINER
用于容器与主机之间的数据拷贝:
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH
docker cp [OPTIONS] SRC_PATH CONTAINER:DEST_PATH
# OPTIONS:
# -a,--archive:文档模式,拷贝所有的uid/gid信息
# -L,--follow-link:保持源目标中的链接不变
2
3
4
5
注意:使用IMAGE ID / CONTAINER ID指定镜像 / 容器,可以通过截断的ID号进行指定,如:
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 62d49f9bab67 4 days ago 133MB
ubuntu latest 26b77e58432b 2 weeks ago 72.9MB
# 删除镜像nginx:latest
docker rmi 62
2
3
4
5
6
如果要导出本地某个容器,可以使用 docker export 命令
docker export 1e560fca3906 > ubuntu.tar
docker export red_panda > latest.tar
docker export -o="latest.tar" red_panda
2
3
导入容器快照 可以使用 docker import 从容器快照文件中再导入为镜像
docker import my_ubuntu_v3.tar jb51/ubuntu:v4
# 从远程位置导入
docker import https://example.com/exampleimage.tgz
# 从本地文件导入
docker import - exampleimagelocal:new
# 提交消息导入
docker import -m "New image imported from tarball" - exampleimagelocal:new
# 从本地存档导入
docker import /path/to/exampleimage.tgz
# 从具有新配置的本地目录导入
docker import -c "ENV DEBUG=true" - exampleimagedir
2
3
4
5
6
7
8
9
10
11
导入导出总结:
save保存的是镜像,export保存的是容器
load用来载入镜像包,import用来载入容器包,但两者都会恢复为镜像
load不能对载入的镜像重命名,而import可以为镜像指定新名称
load不能载入容器包,import能载入镜像包,但不能使用
2
3
4
# 仓库管理
Docker Hub 镜像仓库 (opens new window)
注册账号
登录
docker login
拉取镜像
docker pull ubuntu
推送镜像
docker tag ubuntu:18.04 username/ubuntu:18.04
docker push username/ubuntu:18.04
2
3
4
5
6
7
8
Docker私有仓库
仓库也是一个镜像,直接从官方拉取安装
docker run -d -p 5000:5000 --restart=always --name registry registry
仓库目录挂在宿主机器上
docker run -d -p 5000:5000 -v /opt/data/registry:/var/lib/registry registry
推送仓库: docker push 主机ip:5000/ubuntu:latest
拉取镜像: docker pull 主机ip:5000/ubuntu:latest
2
3
4
5
6
7
8
9
10
11
12
# Docker相关文件和工具
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
指令详解
FROM:定制的镜像都是基于 FROM 的镜像
RUN:用于执行后面跟着的命令行命令。有以下俩种格式:
RUN 命令行命令
RUN ["可执行文件", "参数1", "参数2"]
COPY: 复制指令,从上下文目录中复制文件或者目录到容器里指定路径。
例如: COPY home /mydir/
CMD: RUN 指令,用于运行程序,但二者运行的时间点不同
- CMD 在docker run 时运行。
- RUN 是在 docker build。
ENTRYPOINT: 类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。
但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 ENTRYPOINT 指令指定的程序。
可以搭配 CMD 命令使用:一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参
ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参
容器内会默认运行以下命令,启动主进程。
nginx -c /etc/nginx/nginx.conf
ENV: 设置环境变量,定义了环境变量
ENV NODE_VERSION 7.2.0
设置 NODE_VERSION = 7.2.0 , 在后续的指令中可以通过 $NODE_VERSION
ARG: 构建参数,与 ENV 作用一致。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker
build 的过程中有效,构建好的镜像内不存在此环境变量
VOLUME: 定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。
VOLUME ["路径1", "路径2"...]
将容器内容的目录挂在宿主机中,防止容器重启数据丢失
EXPOSE: 声明端口
EXPOSE 端口1 [端口2...]
WORKDIR: 指定工作目录,用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在
WORKDIR 工作目录路径
USER: 用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。
USER 用户名[:用户组]
HEALTHCHECK: 用于指定某个程序或者指令来监控 docker 容器服务的运行状态
ONBUILD: 用于延迟构建命令的执行(本次构建不执行,新的构建执行其配置的命令)
ONBUILD 其它指令
LABEL: 指令用来给镜像添加一些元数据
LABEL key=value
添加镜像的作者:
LABEL org.opencontainers.image.authors="runoob"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
Compose 是用于定义和运行多容器 Docker 应用程序的工具
通过yml来管理
安装
curl -L https://get.daocloud.io/docker/compose/releases/download/v2.4.1/docker-compose-`uname -s`-`uname -m` /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
docker-compose --version
yml 配置指令参考
version: 指定本 yml 依从的 compose 哪个版本制定的。
build: 指定为构建镜像上下文路径
command: 覆盖容器启动的默认命令
container_name: 指定自定义容器名称,而不是生成的默认名称。
depends_on: 设置依赖关系
deploy:指定与服务的部署和运行有关的配置
dns: 自定义 DNS 服务器,可以是单个值或列表的多个值。
dns_search: 自定义 DNS 搜索域。可以是单个值或列表。
entrypoint: 覆盖容器默认的 entrypoint。
env_file: 从文件添加环境变量。可以是单个值或列表的多个值。
environment: 添加环境变量
expose: 暴露端口仅可以指定内部端口为参数
extra_hosts: 添加主机名映射
healthcheck: 用于检测 docker 服务是否健康运行。
image: 指定容器运行的镜像
logging: 服务的日志记录配置。
network_mode: 设置网络模式
restart: 重启策略
secrets:存储敏感数据
security_opt: 修改容器默认的 schema 标签
stop_grace_period: 指定在容器无法处理 SIGTERM 等待多久后发送 SIGKILL 信号关闭容器
volumes 将主机的数据卷或着文件挂载到容器里。
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Docker Machine 是一种可以让您在虚拟主机上安装 Docker 的工具
并可以使用 docker-machine 命令来管理主机
[更多](https://www.runoob.com/docker/docker-machine.html)
2
3
4
Docker Swarm 是 Docker 的集群管理工具。它将 Docker 主机池转变为单个虚拟 Docker 主机。
Docker Swarm 提供了标准的 Docker API,所有任何已经与 Docker
守护程序通信的工具都可以使用 Swarm 轻松地扩展到多个主机
[更多](https://www.runoob.com/docker/docker-swarm.html)
2
3
4
5
// Make sure to add code blocks to your code group
# Docker实践
# 搭建一个自动化部署项目
- 安装gitea(一个轻量级的git仓库)
1.使用 docker search gitea搜索gitea镜像
2.使用docker pull 拉去需要的镜像
3.使用docker run -d --name gitea --restart=always -p 4000:22 -p 4001:3000 -v 宿主机挂载到docker的目录:docker中的目录位置 gitea的镜像名字
例:
mkdir /home/gitea
docker run -d --name gitea --restart=always -p 3001:22 -p 3000:3000 -v /home/gitea:/data gitea/gitea
4.进入容器 添加用户
docker exec -it gitea /bin/sh
su git
gitea admin create-user --username xxxx --password xxxx --email xxxxx
2
3
4
5
6
7
8
9
10
- 安装jenkins
1、搜索拉取jenkins镜像
docker search jenkins
docker pull jenkins/jenkins
首先需要新建文件夹,用来挂载docker目录
mkdir -pv /usr/local/jenkins
修改目录权限
chmod 777 /usr/local/jenkins
2、运行镜像
docker run --name jenkins -p 8000:8080 -p 50000:50000 \
--restart=always -u root \
-v /var/run/docker.sock:/var/run/docker.sock \
-v $(which docker):/bin/docker \
-v /usr/lib64/libltdl.so.7:/usr/lib/x86_64-linux-gnu/libltdl.so.7 \
-v /var/lib/docker/tmp:/var/lib/docker/tmp \
-v /usr/local/jenkins:/var/jenkins_home \
-d jenkins/jenkins
参数说明:
--restart=always #Docker重启后该容器也为随之重启
-u root
#以root的身份去运行镜像(避免在容器中调用Docker命令没有权限)
#最好使用docker用户去运行
-v $(which docker):/bin/docker
#将宿主机的docker命令挂载到容器中
#可以使用which docker命令查看具体位置
-v /var/run/docker.sock:/var/run/docker.sock
#容器中的进程可以通过它与Docker守护进程进行通信
-v /usr/lib64/libltdl.so.7:/usr/lib/x86_64-linux-gnu/libltdl.so.7
#libltdl.so.7是Docker命令执行所依赖的函数库
#容器中library的默认目录是 /usr/lib/x86_64-linux-gnu/
#把宿主机的libltdl.so.7 函数库挂载到该目录即可
#可以通过whereis libltdl.so.7命令查看具体位置
#centos7位置/usr/lib64/libltdl.so.7
#ubuntu位置/usr/lib/x86_64-linux-gnu/libltdl.so.7
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
在下面路径在获取初始化密码
/var/jenkins_home/secrets/initialAdminPassword
对于前端来讲,主要安装的插件就是nodejs、git,ssh等具体按需安装 webhook 安装插件Generic Webhook Trigger
- 创建项目
安装好express和vue脚手架 > npm install -g @vue/cli > npm install -g express
1
2
3
4
5
1、使用express初始化一个项目 express node-demo 2、使用vue脚手架初始化一个项目 vue create vue-demo
### 总结
#### Docker 存在的意义
- 使用dokcer加速本地开发和构建,开发人员可以构建、运行并分享Docker容器,容器可以在开发环境中构建,然后轻松地提交到测试环境中,并最终进入生产环境
- 能够让独立服务或应用程序在不同环境中,得到相同的运行结果。
- 用docker 创建隔离环境进行测试
- docker 可以让开发者先在本机上构建一个复杂的程序测试,而不是一开始就在生产环境进行测试
- 对我们而言,我们可以方便的进行部署我们的项目,能进行一些自动化的管理
2
3
4
5
6
7
8
9
10
11
12
13