# docker 简介
# 什么是 docker
docker (opens new window) 是一种容器化平台,旨在简化应用程序的部署、管理和运行。它使用容器技术,允许开发人员将应用程序及其所有依赖项打包到一个称为容器的独立单元中。这使得应用程序能够在不同的环境中以一致的方式运行,而不会受到底层系统的影响。
# docker 的关键概念和组件
1. 容器(Containers)
容器是一种轻量级、可移植的单元,包含应用程序和其所有依赖项(库、运行时、系统工具等)。容器是独立于底层系统的,因此可以在任何支持 docker 的环境中运行。
2. 镜像(Images)
镜像是容器的静态快照,包含了运行应用程序所需的所有文件和设置。镜像可以被分享、存储和复制,而容器则是在镜像的基础上运行的实例。
3. Dockerfile
Dockerfile 是一个文本文件,包含创建 docker 镜像所需的一系列指令。通过编写 Dockerfile,开发人员可以定义应用程序的环境、依赖和配置,从而生成可重复的镜像。
4. Docker 镜像仓库(Docker Registry)
镜像仓库是存储和分享 docker 镜像的地方。Docker Hub (opens new window) 是一个公共的 docker 镜像仓库,开发人员可以从中获取官方和社区创建的镜像。此外,企业也可以建立私有的镜像仓库,以存储和分享自己的镜像。
5. Docker Compose
Docker Compose (opens new window) 是一个工具,允许定义和管理多容器 docker 应用程序的配置。通过使用 YAML 文件,开发人员可以描述多个服务、网络和卷,并通过一条命令启动整个应用程序。
6. Docker Swarm
Docker Swarm (opens new window) 是 docker 的原生集群和编排工具,用于在多个主机上管理和运行容器化应用程序。它允许开发人员将多个 docker 主机组成一个虚拟集群,以便提高应用程序的可伸缩性和可用性。
# docker 的优势
一致性:由于容器包含了应用程序及其依赖项,因此可以确保在不同的环境中一致运行。
轻量级:容器共享主机内核,因此相比于虚拟机,它们更轻量、更快速启动和停止。
可移植性:docker 容器可以在任何支持 docker 的环境中运行,从本地开发环境到云服务都能够实现部署。
易于管理:docker 提供了简单的命令行工具,以及图形用户界面,使得容器的创建、启动、停止和删除等操作变得非常容易。
# docker 容器文件系统
# Dockerfile
用于产生 docker 镜像。
Dockerfile 按照步骤构建,产生文件系统。
Dockerfile 是镜像的配置文件,高度可配置。
# docker 安装
接下来主要介绍如何在 Linux 系统上(CentOS 7)安装 docker。
# 1. 卸载旧版本的 docker
旧版本的 Docker 称为 docker 或者 docker-engine ,使用以下命令卸载旧版本:
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine
2
3
4
5
6
7
8
9
10
# 2. 安装需要的依赖包
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# 3. 添加 yum 软件源
执行下面的命令添加官方源:
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
如果网络较慢,可以使用国内源:
sudo yum-config-manager --add-repo https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce .repo
# 4. 安装 docker-ce
sudo yum install docker-ce docker-ce-cli containerd.io
到此,docker 就安装成功了。
# docker 卸载
- 查询 docker 安装过的包
yum list installed | grep docker
- 删除安装包
yum remove [安装包名称]
- 删除镜像/容器等
rm -rf /var/lib/docker
# docker 中国官方镜像加速
- 进入以下文件
vi /etc/docker/daemon.json
- 输入以下内容
{
"registry-mirrors": ["https://registry.docker-cn.com"]
}
2
3
- 执行以下命令
systemctl daemon-reload
- 重启 docker
systemctl restart docker
配置好之后,下次使用 docker pull 命令拉取镜像的时候,就会优先去 docker 中国镜像区拉取镜像,速度会快很多。
# docker 常用命令
# 启动 docker
systemctl start docker
# 停止 docker
systemctl stop docker
# 重新启动 docker
systemctl restart docker
# 查看 docker 运行状态
systemctl status docker
# 查看已有的镜像
docker images
# 删除某个镜像
docker rmi [镜像id]
# 查看已有的容器
docker ps # 查看正在运行的容器
docker ps -a # 加上 `-a` 的话可以查看所有的容器,包括已停止运行的
docker ps -a | grep [容器名称或容器 id] # 查找某个容器
2
3
4
# 启动某个容器
docker start [容器名称]
# 停止运行中的容器
docker stop [容器名称]
# 删除某个容器
docker rm [容器名称/容器 id]
如果容器还在运行中,是无法删除的,必须先使用 docker stop 命令停止容器,再进行删除。
# 打印容器的相关信息
docker logs -f [容器名称] # 加 `-f` 表示持续打印
# 进入某个容器
docker exec -ti [容器名称] /bin/bash
# 容器中安装常见的包
执行以上命令进入容器内。
执行以下命令同步 /etc/apt/sources.list 和 /etc/apt/sources.list.d 中列出的源的索引,获取到最新的软件包。
apt-get update
- 安装第三方包。
apt-get install [包名称]
# 示例
apt-get install wget
apt-get install vim
apt-get install nodejs
apt-get install npm
2
3
4
5
6
7
- 卸载已安装的包。
apt-get remove [包名称]
# 备份 docker 容器内部数据的方法
# 方法一
会生成新的镜像,占用服务器资源,需要手动删除。
# 根据容器名称查找容器
docker ps | grep jenkins_tnd
# commit 镜像
docker commit 00cf89353d88 blog:1.0
# 根据镜像名称查找镜像
docker images | grep blog
# 运行镜像并将宿主机的 /tmp 目录映射到容器内部的 /tmp 目录
# -v 表示映射关系。冒号前是宿主机内的目录,冒号后是容器内的目录
docker run -itd -v /tmp:/tmp blog:1.0
# 查看运行的镜像信息
docker ps | grep blog:1.0
# 将镜像内的 /var/jenkins_home 复制到宿主机的 /tmp 目录中
docker exec -it epic_fermi cp -r /var/jenkins_home /tmp
# 生成的 jenkins_home 目录里包含的就是 jenkins_tnd 容器的数据
# 将生成的 jenkins_home 目录移动到 home 目录中,因为 tmp 目录在服务器重启之后数据会丢失
mv jenkins_home /home
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 方法二
官方文档提到的备份方法 (opens new window)
不会生成新的镜像,新的镜像在数据备份完成后会自动删除。
# 使用 --volumes-from 命令将容器内的数据挂载到宿主机中,并生成压缩包
docker run --rm --volumes-from jenkins_tnd -v /tmp/backup:/backup ubuntu tar cvf /backup/backup.tar /var/jenkins_home
# 生成的压缩包就在 /tmp/backup 目录中
cd /tmp/backup
# 解压压缩包
tar xvf backup.tar
2
3
4
5
6
7
8
解压后会生成一个新的目录 var,里面就放着从 jenkins_tnd 容器中导出来的数据。同样的,我们也需要使用 mv 命令将它移动到其他目录中,才能永久保存。
# 方法三
# 根据容器名称查找容器
docker ps | grep jenkins_tnd
# 直接将容器内存储数据的目录拷贝到宿主机的 tmp 目录中
docker cp 00cf89353d88:/var/jenkins_home /tmp
2
3
4
5
可以看到同样生成了一个 jenkins_home 目录,里面保存的就是容器内的数据。
# docker-compose
# docker-compose 介绍
docker-compose (opens new window) 命令可以让我们一次性创建并运行多个服务,而不需要一个一个手动去创建和运行。
除此之外,使用 docker-compose 的另一个好处是,我们可以很清晰的在 docker-compose.yml 文件中看到不同容器的信息,包括端口号映射、数据挂载等等。
安装完 dcoker-compose 之后,还需要手动创建并配置 docker-compose.yml 文件。比如配置一个 jenkins 容器如下:
version: '3'
services:
jenkins:
container_name: 'jenkins_tnd'
image: jenkins/jenkins:lts
restart: always
user: jenkins:994
ports:
- "8082:8080"
volumes:
- /home/jenkins_tnd:/home/jenkins_home
- /usr/bin/docker:/usr/bin/docker
- /var/run/docker.sock:/var/run/docker.sock
2
3
4
5
6
7
8
9
10
11
12
13
# 安装 docker-compose
- 下载 docker-compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
- 查看是否安装成功
docker-compose --version
- 给 docker-compose 添加执行权限
sudo chmod +x /usr/local/bin/docker-compose
- 编辑 docker-compose.yml 文件
vi docker-compose.yml
- 运行 docker-compose.yml 文件,创建文件中配置的容器
docker-compose up -d
# 卸载 docker-compose
rm /usr/local/bin/docker-compose
# 推送本地镜像到远程仓库
- 在终端中登录到 docker hub
docker login
- 提交本地镜像,commit 后面带的是本地镜像的 id 以及在远程仓库显示的镜像名称
docker commit 3aa60a25c53d tuoniaodan/mysql
- 推送到远程仓库
docker push tuoniaodan/mysql
推送成功后,就可以在远程自己的 docker hub 仓库中看到它了。之后我们就可以通过 docker pull
命令将它拉取下来使用了。
# docker 安装 jenkins
# 使用 docker run 创建容器
- 拉取最新的 jenkins 镜像
docker pull jenkins/jenkins:lts
- 创建 jenkins 容器
# --name 表示给容器命名;-itd 表示增加交互式的终端以及后台执行;-p 8082:8080 表示指定本地的 8082 端⼝映射到容器内的 8080 端口
docker run --name jenkins_tnd -itd -p 8082:8080 \
-v /home/jenkins_tnd:/home/jenkins_home \
-v /usr/bin/docker:/usr/bin/docker \
-v /var/run/docker.sock:/var/run/docker.sock \
jenkins/jenkins:lts
2
3
4
5
6
# 使用 docker-compose 创建容器
注意
实际项目中推荐使用这种方式!
# 安装与配置
- 通过 docker logs 命令获取 jenkins 初始密码
docker logs -f jenkins_tnd
- 指定宿主机映射到容器的端口永久通过防火墙,比如这里是 8082,并重新加载防火墙
# 指定 8082 端口永久通过防火墙
firewall-cmd --add-port=8082/tcp --permanent
# 重新加载防火墙
firewall-cmd --reload
2
3
4
5
- 在浏览器中访问 121.4.83.104:8082 就可以看到 jenkins 的欢迎页面了,接下来就是对 jenkins 的各项配置了。配置方法参照:Jenkins 配置。
# 编写 shell 脚本
#!/bin/bash
CONTAINER=${container_name}
PORT=${port}
# 完成镜像构建
docker build --no-cache -t ${image_name}:${tag} .
RUNNING=${docker inspect --fotmat="{{ .State.Running }}" $CONTAINER 2 > /dev/null}
if [ ! -n $RUNNING ]; then
echo "$CONTAINER does not exit"
return 1
fi
if [ "$RUNNING" == "false" ]; then
echo "$CONTAINER is not running."
return 2
else
echo "$CONTAINER is running."
# 删除同名的容器
matchingStarted=$(docker ps --filter="name=$CONTAINER" -q | xargs)
if [ -n $matchingStarted ]; then
docker stop $matchingStarted
fi
matching=$(docker ps -a --filter="name=$CONTAINER" -q | xargs)
if [ -n $matching ]; then
docker rm $matching
fi
fi
echo "RUNNING is $RUNNING"
# 运行服务
docker run -itd --name $CONTAINER -p $PORT:80 ${image_name}:${tag}
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
# 问题记录
📌 1. docker 的 jenkins 容器里的时间跟宿主机时间不一致
使用
date
命令可以查看当前时间。使用
docker exec -it -u root jenkins_tnd bash
命令可以进入到 jenkins 容器,使用exit
命令可以退出容器。
解决方法是:
- 复制上海时区到
/etc/localtime
。
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
此时,jenkins 容器的时间就恢复正常了。
📌 2. 配置 git 的时候报错
解决办法是:
使用 ssh 的方式进行验证,如下:
添加凭据时选择 SSH Username with private key
,然后输入 Username 和 Private Key。配置好之后就不会报错了。
注意
这里的私钥需要在服务器上重新生成,使用如下命令:
ssh-keygen -t rsa -C "2982093545@qq.com"
生成后的公钥和私钥如下,将公钥添加到 gitee 上,将私钥添加到 Jenkins 的凭据中。
📌 3. 构建时报文件执行权限错误
解决方法是:
在构建脚本前面加上 #!/bin/bash
就可以了。
📌 4. /var/run/docker.sock 无权限
解决方法:
- 方法一
只要 docker 服务重启,就需要重新设置一次。
chmod 666 /var/run/docker.sock
- 方法二
只需要设置一次。
# 添加 docker用户组
groupadd docker
# 把当前用户加入 docker 用户组
gpasswd -a ${USER} docker
# 查看是否添加成功
cat /etc/group | grep ^docker
# 更新用户组
newgrp docker
# 重启 docker
systemctl restart docker
2
3
4
5
6
7
8
9
10
11
12
13
14
其他方法可参考这里 (opens new window)。
📌 5. 碰到一些奇怪的问题时,可以重启 docker 试试
解决方法:
重启 docker
systemctl restart docker