【docker 简介】
一、什么是docker
Docker 是一个基于go语言开发的开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
二、docker核心概念
docker三大核心概念:镜像 Image、容器 Container、仓库 Repository
- 镜像(Image):Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。
- 容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。基于镜像可以创建容器,同一个镜像可以创建多个容器;
docker | 面向对象 |
容器 | 对象 |
镜像 | 类 |
- 仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像。镜像存放在仓库中,可以从仓库中拉取。
三、docker架构及原理
- Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。
- 架构上可以分为客户端和服务端;
- Docker Daemon是docker的守护进程;
- containerd是容器运行的进程,是实现容器的核心;
- 客户端通过内部的API和服务端的守护进程进行交互,守护进程再通过containerd分发到各个容器;
概念 | 说明 |
Docker 镜像(Images) | Docker 镜像是用于创建 Docker 容器的模板。基于镜像可以创建容器,同一个镜像可以创建多个容器; |
Docker 容器(Container) | 容器是独立运行的一个或一组应用,是镜像运行时的实体。 |
Docker 客户端(Client) | Docker 客户端通过命令行或者其他工具使用 Docker SDK (https://docs.docker.com/develop/sdk/) 与 Docker 的守护进程通信。 |
Docker 主机(Host) | 一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。 |
Docker Registry | Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。镜像仓库分为公共镜像仓库Docker Hub和一些私有化部署的仓库比如:Harbor(这两种类似于github和gitlab)Docker Hub(https://hub.docker.com) 提供了庞大的镜像集合供使用。一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。 |
Docker Machine | Docker Machine是一个简化Docker安装的命令行工具,通过一个简单的命令行即可在相应的平台上安装Docker,比如VirtualBox、 Digital Ocean、Microsoft Azure。 |
四、docker轻量级的实现原理
docker容器本质上是宿主机的进程,Docker通过namespace实现了资源隔离,通过cgroups实现了资源限制,通过写时复制机制(copy-on-write)实现了高效的文件操作。
namespace资源隔离
linux内核提拱了6种namespace隔离的系统调用:
namespace | 系统调用参数 | 隔离内容 |
UTS | CLONE_NEWUTS | 主机名或域名 (since Linux 2.6.19) |
IPC | CLONE_NEWIPC | 信号量、消息队列和共享内存(since Linux 2.6.19) |
PID | CLONE_NEWPID | 进程编号(since Linux 2.6.24) |
Network | CLONE_NEWNET | 网络设备、栈、端口等(since Linux 2.6.24) |
Mount | CLONE_NEWNS | 挂载点(文件系统)(since Linux 2.6.24) |
User | CLONE_NEWUSER | 用户组和用户组(started in Linux 2.6.23 and completed in Linux 3.8) |
五、docker的优缺点
1.优点
- 更高效利用系统资源
- 更快速的启动时间
- 一致的运行环境
- 持续交付和部署
- 更轻松的迁移
2.缺点
- Docker是基于Linux 64bit的,无法在32bit的 linux/Windows/unix环境下使用
- Docker并非适合所有应用场景,Docker只能虚拟基于 Linux的服务
- Docker实例是无状态的,不会保存当前操作行为的数据:容器销毁后,再次创建容器不会保存之前的数据,一种方法是通过数据挂载技术将数据挂载到宿主机指定目录来解决此问题,另一种方法是通过docker commit命令来基于已有容器构建为新的镜像,从而达到环境持久化的目的。
【docker 安装与启动】
一、docker安装与启动
1.安装docker的几种方式
1)安装最新版本docker
① 先卸载旧版本的docker
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
② 指定Docker下载源(可选,适用于首次安装)
yum install -y yum-utils
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
③ 安装Docker(默认安装最新版本)
yum install -y docker-ce docker-ce-cli containerd.io
④ 验证是否安装成功
docker version
2)安装指定版本的docker
yum list docker-ce --showduplicates | sort -r # 查看所有可用版本
yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io # 安装指定版本
3)通过脚本一键安装docker
脚本内容如下:
#!/bin/bash
echo "set default docker install repo"
yum install -y yum-utils
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
echo "install docker ..."
yum install -y docker-ce docker-ce-cli containerd.io
systemctl start docker
systemctl status docker
2.启动docker
systemctl start docker # 启动服务
systemctl status docker # 查看状态
systemctl stop docker # 停止服务
systemctl restart docker # 重启服务
二、创建第一个docker容器
1.创建容器
按照国际惯例,先运行一个hello-world的容器
docker run hello-world
# 如果网络等一切正常的话,会出现如下提示,表示容器已经创建成功
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:18a657d0cc1c7d0678a3fbea8b7eb4918bba25968d3e1b0adebfa71caddbc346
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
2.查看容器
docker ps -a # 查看所有容器
# 创建成功,容器列表中就会有hello-world的容器,但名字不是hello-world,因为我们在运行容器时并未指定名称
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a07f1a8ea1a4 hello-world "/hello" 21 seconds ago Exited (0) 20 seconds ago adoring_chatterjee
三、卸载docker
1.常规方式卸载
① 停止docker服务
systemctl stop docker
② 搜索已经安装的docker安装包
yum list installed | grep docker
rpm -qa | grep docker
yum -y remove docker-ce.x86_64
yum -y remove docker-ce-cli.x86_64
yum -y remove containerd.io.x86_64
③ 移除所有相关安装包
yum -y remove contained.io.x86_64
④ 删除docker镜像及相关文件夹
rm -rf /var/lib/docker
2.脚本卸载
所谓的使用脚本安装和卸载,通俗理解就是把上述多个操作步骤的命令放在一个脚本中批量执行,内容如下:
#!/bin/bash
systemctl stop docker
yum -y remove docker-ce.x86_64
yum -y remove docker-ce-cli.x86_64
yum -y remove containerd.io.x86_64
rm -rf /var/lib/docker
rm -rf /etc/docker/daemon.json
【docker 常用操作命令】
一、镜像操作命令
命令 | 说明 |
pull | 拉取镜像 |
search | 搜索相关镜像 |
tag | 重命名镜像 |
rmi | 删除镜像 |
images 或 image ls | 查看所有镜像 |
build | 基于Dockerfile构建镜像 |
commit | 基于已有容器构建镜像 |
1.拉取镜像
使用”docker pull 镜像名称”,拉取远程仓库的镜像到本地(先校验本地是否存在,本地不存在时再默认从官网拉取最新版本的镜像)
以busybox为例:
BusyBox 是一个集成了三百多个最常用Linux命令和工具的软件。BusyBox 包含了一些简单的工具,例如ls、cat和echo等等,还包含了一些更大、更复杂的工具,例grep、find、mount以及telnet。有些人将 BusyBox 称为 Linux 工具里的瑞士军刀。简单的说BusyBox就好像是个大工具箱,它集成压缩了 Linux 的许多工具和命令,也包含了 Linux 系统的自带的shell。
docker pull busybox # 拉取镜像
在拉取镜像前,也可以通过docker search命令搜索不同类型的镜像
docker search busybox # 搜索相关镜像
2.查看镜像
使用 “docker image ls” 或 “docker images” 命令查看本地已经存在的镜像
docker images # 查看所有镜像
docker images | grep busybox # 查看指定镜像
3.修改镜像名称
使用 “docker tag 原始镜像名称 新名称” 命令重命名镜像,如:docker tag busybox:latest mybusybox:V1.0,重命名镜像会新增一条镜像,相当于创建了一个副本,但ID相同。
docker tag busybox:latest mybusybox:V1.0
4.删除镜像
使用 “docker rmi 镜像名称” 命令删除无用镜像,通过镜像名称删除,只会删除指定名称的镜像;通过镜像ID删除,会删除所有ID相同的镜像。
docker rmi mybusybox:V1.0
docker rmi -f ff4a8eb070e1
二、容器操作命令
容器操作命令:
命令 | 说明 |
create | 创建容器 |
run | 运行容器,run = pull + create + start |
exec…-it…sh | 进入容器内部 |
start | 启动容器 |
restart | 重启容器 |
stop | 停止容器 |
rm | 删除容器 |
commit | 基于已有容器构建镜像 |
ps | 查看容器状态:docker ps -a:查看所有容器docker ps -l:查看最近操作的容器 |
logs | 查看容器日志:docker logs 容器名:查看指定容器的运行日志docker logs -f 容器名:实时查看指定容器的运行日志 |
容器操作相关参数:
命令 | 说明 |
–name | 指定容器名称:–name=容器名–name 容器名 |
-d | 后台运行 |
-p | 映射端口,宿主机端口:容器端口,例如:-p 3307:3306 |
-v | 挂载目录到本地,宿主机目录:容器目录,例如:-v /usr/local/nginx:/usr/local/nginx |
–restart | 自动重启,例如:–restart=always,跟随docker服务的重启而重启 |
1.创建容器
docker create (–name=容器名) 镜像名,例如:
docker create --name=mybusybox busybox
2.查看容器状态
docker ps -a # 查看所有容器
docker ps -a | grep mybusybox # 过滤查看指定容器
docker ps -l # 查看最近操作的容器
通过create命令创建完成后的容器是”Created”状态的,可以通过start命令来启动容器
3.启动容器
docker start mybusybox
4.进入容器
通过”docker exec -it 容器名 sh”命令进入容器内部,例如:
docker exec -it mybusybox sh
5.运行容器
docker run = docker pull + docker create + docker start
docker run --name=mynginx -d -p 81:80 nginx
6.停止容器
docker stop 容器名或容器ID,例如:
docker stop mybusybox
docker stop 6fbf5a7a580b
7.删除容器
docker rm 容器名或容器ID,删除前要先停止容器,例如:
docker stop mybusybox
docker rm mybusybox
docker rm 6fbf5a7a580b
8.查看容器日志
- docker logs 容器名或容器ID:以文件形式查看日志,类似 cat;
- docker logs 容器名或容器ID:实时查看日志,类似 tail -f;
例如:
docker logs sonic_sonic-server-controller_1
docker logs -f sonic_sonic-server-controller_1
9.基于已有容器构建为新的镜像模板
用法:docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
OPTIONS | 释义 |
-a | 标注作者信息 |
-c | 使用Dockerfile指令来生成镜像 |
-m | 提交说明信息,类似于git commit -m “xxxx” |
-p | 在提交时,暂停容器 |
例如:当前有个需求,将当前服务器上正在运行的一个容器,无痕迁移到另一台服务器上运行。意味着需要执行以下步骤:
将当前正在运行的容器构建为新的镜像A>>将新镜像A的镜像文件复制到另一台服务器或直接将镜像A提交到镜像仓库>>在另一台服务器上将镜像A从镜像仓库下载下来>>基于镜像A创建容器并运行
① 打包容器
为了便于演示,先将一个文件复制到已有容器内
docker cp jdk_install.sh mysql:/home
② 查看容器内文件
docker exec -it mysql sh
可以看到,已经将jdk_install.sh文件复制到了mysql容器的/home目录下:
③ 基于容器构建新的镜像
docker commit -a "chenjigang" mysql new-mysql
通过”docker images”命令查看当前镜像列表,可以看到名为new-mysql的镜像:
④ 基于新镜像运行容器
docker run -d --name new-mysql-container -e MYSQL_ROOT_PASSWORD=123456 -p 3308:3306 new-mysql
⑤ 查看容器内文件
docker exec -it new-mysql-container sh
通过下图可以看出,之前复制到容器内的jdk_install.sh文件,已经保存到镜像中、并跟随出现在新的容器内:
【docker 使用技巧】
一、更换镜像源
1.配置文件路径:/etc/docker/daemon.json,若不存在则新建此文件
{
"registry-mirrors":[
"http://registry.docker-cn.com",
"http://docker.mirrors.ustc.edu.cn",
"http://hub-mirror.c.163.com",
"http://cr.console.aliyun.com/",
"https://8wb4g36l.mirror.aliyuncs.com"
]
}
2.配置完成后重启docker服务
systemctl restart docker.service
二、更换存储目录
docker安装完成后,默认存储路径为/var/lib/docker。创建容器后,每个容器的数据卷容量上限与/var/lib/docker所在的挂载的磁盘大小有关。例如下图所示:挂载的磁盘大小为50GB,则docker容器数据卷上限就是50GB,如果有多个容器,则这些容器共享50GB的容量,而且同时也与挂载磁盘下的其他目录共享使用。那么如果运行的容器数量较多,或是遇到需要存储大量数据如gitlab这类容器,50G显然就有些捉襟见肘。此时可以通过修改docker存储路径的方式扩容容器的容量上限。特别提一句,docker存储路径最好尽早修改,这样可以避免后期因磁盘写满导致的各种容器运行异常问题。
三种方式修改docker存储路径,分别为:
1.方式一:修改docker配置文件
编辑docker配置文件
vi /usr/lib/systemd/system/docker.service
使用”–graph”或”-g”参数指定存储位置
ExecStart=/usr/bin/dockerd --graph /home/docker_home
修改完成后重新加载配置文件并重启docker服务
// reload配置文件
systemctl daemon-reload
// 重启docker
systemctl restart docker.service
2.方式二:创建daemon.json文件
docker1.12或以上版本,可以创建或修改daemon.json文件来指定存储位置。docker查看版本命令“docker version”
vi /etc/docker/daemon.json
在最后添加graph字段,定义docker目录
{
"registry-mirrors":[
"http://registry.docker-cn.com",
"http://docker.mirrors.ustc.edu.cn",
"http://hub-mirror.c.163.com",
"http://cr.console.aliyun.com/",
"https://8wb4g36l.mirror.aliyuncs.com"
],
"graph": "/home/docker_home"
}
修改完成后同样需要重新加载配置文件、重启docker服务
systemctl daemon-reload
systemctl restart docker.service
3.方式三:创建软链接(推荐)
前两种方式适用于首次安装docker后没有pull过镜像、创建过容器。即使修改了存储路径,因为没有镜像和容器,所以也不会产生任何影响。
创建软链接的方式,适用于已经创建过容器、并且容器已经产生数据的情况。这种方式可以避免对镜像及现有容器数据造成破坏,以及更改存储路径后找不到数据的情况。具体步骤如下:
① 查看docker路径
默认情况下Docker的存放位置为:/var/lib/docker,也可以通过如下命令查看docker存储路径
docker info | grep "Docker Root Dir"
② 停掉docker服务
systemctl stop docker
③ 移动docker目录
mv /var/lib/docker /home/docker_home
③ 创建软链接
- /home/docker_home为源文件目录,也就是新设置的docker存储目录
- /var/lib/docker为软链接目标目录,与此目录建立链接后,相当于原来的docker配置保持不变,但真正的存储目录是其背后所指向的/home/docker_home
ln -s /home/docker_home /var/lib/docker
④ 启动docker服务
systemctl start docker
修改完成后,我们可以通过以下命令查看docker的存储目录:
docker info | grep "Root Dir"
# 修改成功会返回以下内容:
# Docker Root Dir: /home/docker_home
查看/var/lib/目录,docker目录是一个软链接,指向/home/docker_home,配置正确。
三、修改时区
1.创建容器时设置时区
创建时增加映射使用主机时区
-v /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime
2.创建容器后修改时区
① 查看宿主机时区
通过date -R命令可以看出,宿主机的时区为东八区,查看/etc/localtime,可以看出localtime实际上是一个软链接,背后指向的是/usr/share/zoneinfo/Asia/Shanghai
[root@test_host home]# date -R
Thu, 08 Sep 2022 11:05:37 +0800
[root@test_host home]# ls -l /etc/localtime
lrwxrwxrwx. 1 root root 35 8月 29 17:17 /etc/localtime -> ../usr/share/zoneinfo/Asia/Shanghai
② 拷贝本地时区到docker容器内部
docker cp /usr/share/zoneinfo/Asia/Shanghai docker.ui:/etc/localtime
③ 进入容器内部查看时区
docker exec -it docker.ui sh # 进入docker.ui容器
ls /etc # 查看/etc下是否存在已经复制的localtime文件
date -R # 查看时区
通过下图可以看出,/etc下已经存在了宿主机复制过来的localtime文件,时区为东八区,已经修正。
四、拷贝文件
主要用到”docker cp”命令
1.从宿主机拷贝到容器
docker cp 宿主机文件路径 容器名:目录,例如:
docker cp redis_log mysql:/home
2.从容器内拷贝到宿主机
docker cp 容器名:文件路径 宿主机目录,例如:
docker cp mysql:/home/mayfly-go.sql /home/
五、常见问题解决
1.容器报错ipv4网络不可用
运行容器时报错
如果是容器运行直接报这个错, 解决方式:
① 在宿主机上执行
echo "net.ipv4.ip_forward=1" >>/usr/lib/sysctl.d/00-system.conf
② 重启network和docker服务
systemctl restart network
systemctl restart docker
创建容器时报错
“WARNING: IPv4 forwarding is disabled. Networking will not work.”
如果是运行镜像、创建容器的时候报这个错,则直接重启docker服务:
systemctl restart docker
【docker 一键快速搭建环境】
1.docker一键搭建Jenkins
# 拉取镜像
docker pull jenkins
# 运行容器
docker run -d --name=jenkins -v /home/jenkins:/var/jenkins_home -p 8088:8080 -u root --restart=always jenkins
前台访问:http://192.168.1.122:8088/
注意:首次访问需输入密码,宿主机上密码文件路径为 /home/jenkins/secrets/initialAdminPassword,或是进入容器内查看:/var/jenkins_home/secrets/initialAdminPassword
初始化完成后,原始密码文件自动删除:
2.docker一键搭建Gitlab
# 拉取镜像
docker pull gitlab/gitlab-ce
# 创建gitlab环境变量
export GITLAB_HOME=/home/gitlab
# 运行容器
docker run -d --name=gitlab -u root --restart=always -v $GITLAB_HOME/config:/etc/gitlab -v $GITLAB_HOME/logs:/var/log/gitlab -v $GITLAB_HOME/data:/var/opt/gitlab -p 443:443 -p 8081:80 -p 2222:22 gitlab/gitlab-ce
http://192.168.1.122:8081/ 首次访问会提示修改密码,用户名为 root
3.docker一键搭建Nginx
官网地址:https://hub.docker.com/_/mysql
# 拉取镜像
docker pull nginx
# 运行容器
docker run -d --name mynginx -p 81:80 nginx
浏览器端访问:http://192.168.1.123:81/
4.docker一键搭建MySQL
官网地址:https://hub.docker.com/_/mysql
# 拉取镜像
docker pull mysql
# 运行容器
docker run -d -e MYSQL_ROOT_PASSWORD=123456 --name=mymysql -p 3307:3306 mysql
# 进入mysql容器
docker exec -it mysql sh
# 登录mysql
mysql -uroot -p123456
mysql命令行操作
使用工具连接mysql数据库
5.一键搭建RabbitMQ
# 拉取镜像
docker pull rabbitmq:3.7-management
# 启动容器
docker run --name=rabbitmq -d --restart always -p 15672:15672 -p 5672:5672 -v /home/rabbitmq:/var/lib/rabbitmq rabbitmq:3.7-management
注:如果docker pull rabbitmq后面不带management,启动rabbitmq后是无法打开管理界面的,所以我们需要下载带management插件的rabbitmq
浏览器端访问:http://192.168.1.123:15672/,登录账号和密码都是:guest
【dockerfile 定制镜像】
一、Dockerfile是什么?
1.简介
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
2.作用
Dockerfile的作用:定制镜像,所谓定制镜像,就是以一个镜像为基础,在其上进行定制,丰富功能、提前作一些配置等。
二、Dockerfile常用指令
1.常用指令释义
指令 | 说明 |
FROM | 指定基础镜像 |
MAINTAINER | 增加说明信息,如维护者姓名邮箱等,非必须 |
RUN | 执行具体的linux命令(用于构建镜像时执行相关的命令) |
USER | 基于哪个用户运行容器 |
ADD | 将本地的文件添加到镜像内(支持正则表达式拷贝,支持更多的文件类型的拷贝,如网络文件的下载后拷贝,ADD http://xxxx/test.tar.gz /test/) |
COPY | 将本地文件拷贝到镜像内(只支持基本的文件、文件夹的拷贝,推荐使用COPY),最好将要拷贝的文件置于Dockerfile同一目录下 |
WORKDIR | 目录切换指令,类似于linux的cd命令WORKDIR /home/jenkins_home/conf 等同于以下指令:WORKDIR /homeWORKDIR jenkins_home/conf |
EXPOSE | 指定容器监听的端口,仅作为说明,不会真正生效,还是需要使用docker run -p参数进行端口映射 |
CMD | 类似于RUN指令,区别与CMD是在启动容器时执行相关的命令,CMD echo “hello world” 或 [‘ECHO’,’hello world’]都可以,推荐使用后者列表形式 |
ENTRYPOINT | 指定ENTRYPOINT参数后,使用docker run xxxx 启动容器时,docker run 后面的参数不会被覆盖 |
ENV | 指定运行容器时的环境变量,格式为 KEY=VALUE或KEY VALUE,如ENV VERSION=2.0在后续指令中可以使用$VERSION进行替换2.0 |
VOLUME | 数据栈声明,做匿名挂载用,假设指令为VOLUME /usr/local,则在启动容器后会在服务器上docker默认路径/var/lib/docker/volumes/下自动生成一个文件夹,用于挂载/usr/local,常用于执行docker run命令时忘记指定-v 参数,从而自动保存一些重要的数据时使用 |
2.’CMD’、’ENTERPOINT’、’docker run xxx’ 三者之间的区别与联系
- 若指定了CMD [‘ECHO’,’hello world’],同时使用了docker run -p 8080:80 xxx,则docker run 后面的参数会覆盖CMD后面的指令;
- 若指定了ENTRYPOINT [‘nginx’],同时使用了docker run -p 8080:80 xxx,则会把docker run 后面的参数作为参数传递给ENTRYPOINT,与ENTRYPOINT后面的参数拼接起来;
- 若CMD [‘ECHO’,’hello world’],同时指定了ENTRYPOINT [‘nginx’],则会把CMD后的参数作为参数传递给ENTRYPOINT,与ENTRYPOINT后面的参数拼接起来;
总结:CMD相对更为灵活,用户可以通过docker run 更改dockerfile中CMD的指令,而ENTRYPOINT则更为单一,使用docker run命令行参数启动容器时无法修改dockerfile中ENTRYPOINT的指令;
3.Dockerfile示例
自定义Dockerfile
如下,我们制作一个简单的Dockerfile用来构建镜像,它是基于centos7镜像。其中,执行一些简单的命令,如输出信息、创建文件夹,另外提前添加文件到镜像目录、切换目录,最后安装一个工具,执行查看网卡命令:
# 基于centos7镜像
FROM centos:7
# 维护者信息
MAINTAINER "chenjigang"
# 基于root用户运行容器
USER root
# 运行命令
RUN echo "test dockerfile..."
RUN mkdir -p /home/docker_home
# 本地复制文件到镜像内
COPY docker_install.sh /home/docker_home/docker_install.sh
# 切换目录
WORKDIR /home/docker_home
RUN ls -al
RUN yum install -y net-tools
RUN ifconfig
mysql示例
下图是MySQL的官方镜像的dockerfile,也是用到了上面介绍的各个命令,将其有机地结合,例如:一开始会添加一个文件>>然后运行bash>>创建用户和用户组>>中间设置环境>>设置数据目录>>最后启动mysqld,从而实现MySQL的构建:
三、从Dockerfile构建镜像
Dockerfile 创建完成后,可以使用 docker build 命令根据 Dockerfile 构建一个镜像。Docker build常用的指令包括两个参数:
- -t 指定镜像的名字
- -f 显示指定构建镜像的 Dockerfile 文件,若当前操作目录与Dockerfile文件处于同一目录,则使用.也可以,否则需使用 -f 参数指定Dockerfile文件路径(注:Dockerfile 命名为非固定命名,可更改)
基于上面第一个Dockerfile提交构建:
# 运行当前目录下的Dockerfile文件,生成一个名为mycentos7的镜像
docker build -t mycentos7 .
如下图所示,运行docker build构建镜像命令后,正在按照上述自定义的Dockerfile中的步骤顺序执行:
从下图可以看出,已经成功构建了一个镜像:mycentos7:latest
查看镜像列表,存在新构建的镜像mycentos7:
基于mycentos7镜像创建一个容器:
docker run -it --name mycentos7 mycentos7:latest sh
此时,启动容器,进入镜像shell环境内会发现Dockerfile文件中定义的命令已生效:
- 指定的docker_install.sh已复制到mycentos镜像的/home/docker_home文件夹下;
- net-tools工具已提前安装成功,”ifconfig”命令可以正常执行;
四、Dockerfile构建镜像原理
每多一行命令,镜像就会多一层
【docker-compose 容器编排】
一、Docker-Compose介绍
1.简介
Docker-Compose项目是Docker官方的开源项目,负责实现对Docker多容器编排管理系统。使用 Docker-compose,可以用一个 YAML 文件定义一组要启动的容器,以及容器运行时的属性。 Docker-Compose的工程配置文件默认为docker-compose.yml
项目地址:https://github.com/docker/compose
2.Docker-Compose前世今生
Docker Compose 的前身是 Fig,现阶段 Docker Compose 是 Docker 官方的单机多容器管理系统(不能跨机器),它本质是一个Python 脚本,它通过解析用户编写的 yaml 文件,调用 Docker API 实现动态的创建和管理多个容器。
二、Docker-Compose安装
1.使用curl命令安装(推荐)
# 下载 Docker Compose 的安装包
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 修改 Docker Compose 执行权限
sudo chmod +x /usr/local/bin/docker-compose
2.使用PIP安装
需提前安装Python环境
pip install -U docker-compose
三、Docker-Compose常用指令组成
Docker Compose 文件主要分为三部分: services(服务)、networks(网络) 和 volumes(数据卷)
1.常用指令说明
指令 | 说明 |
image | 镜像名称,基于哪个镜像,使用现有的镜像 |
build | 使用自定义的镜像,若当前docker-compose.yml和Dockerfile在同一路径下,则build的键值用 . 也可以,若不在同一路径下,或Dockerfile文件不是用的默认名称Dockerfile,则需指定Dockerfile的路径 |
command | 启动镜像时用的命令,类似于Dockerfile中的CMD指令 |
container_name | 容器名称 |
depends_on | 指定服务启动顺序,如存在多个服务nginx、db、Jenkins时,则在Jenkins服务下定义depends_on: db,会优先启动db服务 |
links | 解决容器之间的链接,使用db可以链接到db服务,使用别名test_db也可以 |
ports | 指定端口,端口映射时使用,类似于docker命令中的-p参数 |
volumes | 数据挂载时使用,类似于docker命令中的-v参数 |
2.docker-compose.yml示例
支持四种命名格式:docker-compose.yml, docker-compose.yaml, compose.yml, compose.yaml
sonic私有云真机平台:http://192.168.1.20:3000/Index/Devices
下面就以前面分享过的《开源云真机平台-Sonic应用实践》中的sonic服务的docker-compose.yml为例,一起来看看上述指令的用法:
version: '3' # 版本
services: # 服务,
sonic-server-eureka: # 容器名(sonic微服务注册中心)
image: "registry.cn-hangzhou.aliyuncs.com/sonic-cloud/sonic-server-eureka:v1.5.0-release"
hostname: sonic-server-eureka
environment: # 环境,读取配置文件中eureka的用户名密码等
- SONIC_EUREKA_USERNAME
- SONIC_EUREKA_PASSWORD
- SONIC_EUREKA_PORT
- SONIC_EUREKA_HOST=sonic-server-eureka
volumes: # 目录映射
- ./logs/:/logs/
networks: # 网络名
- sonic-network
ports: # 端口映射
- "${SONIC_EUREKA_PORT}:${SONIC_EUREKA_PORT}"
sonic-server-gateway: # 容器名(sonic微服务网关)
image: "registry.cn-hangzhou.aliyuncs.com/sonic-cloud/sonic-server-gateway:v1.5.0-release"
hostname: sonic-server-gateway
environment: # 同样也是一些环境配置,用于和eureka容器通信
- SONIC_EUREKA_USERNAME
- SONIC_EUREKA_PASSWORD
- SONIC_EUREKA_PORT
- SONIC_EUREKA_HOST=sonic-server-eureka
- SECRET_KEY
- EXPIRE_DAY
volumes:
- ./logs/:/logs/
depends_on: # 指定服务启动顺序,先启动sonic-server-eureka容器
- sonic-server-eureka
networks: # 网络,各个容器必须处于同一网络下才能相互通信
- sonic-network
restart: on-failure
sonic-server-controller: # 容器名
image: "registry.cn-hangzhou.aliyuncs.com/sonic-cloud/sonic-server-controller:v1.5.0-release"
environment: # 环境配置,读取数据库、账号等配置
- SONIC_EUREKA_USERNAME
- SONIC_EUREKA_PASSWORD
- SONIC_EUREKA_PORT
- SONIC_EUREKA_HOST=sonic-server-eureka
- MYSQL_HOST
- MYSQL_PORT
- MYSQL_DATABASE
- MYSQL_USERNAME
- MYSQL_PASSWORD
- SONIC_SERVER_HOST
- SONIC_SERVER_PORT
- SECRET_KEY
- EXPIRE_DAY
- REGISTER_ENABLE
- NORMAL_USER_ENABLE
- LDAP_USER_ENABLE
- LDAP_USER_ID
- LDAP_BASE_DN
- LDAP_BASE
- LDAP_USERNAME
- LDAP_PASSWORD
- LDAP_URL
networks:
- sonic-network
volumes:
- ./logs/:/logs/
depends_on:
- sonic-server-eureka
restart: on-failure
sonic-server-folder:
image: "registry.cn-hangzhou.aliyuncs.com/sonic-cloud/sonic-server-folder:v1.5.0-release"
environment:
- SONIC_EUREKA_USERNAME
通过上述配置我们能够发现,docker-compose.yml这个配置文件,就是由前面我们介绍的一个个指令按照一定的格式、顺序、规则进行排列、相结合组成,从而实现不同容器的排编,相互通信,进而实现强大的功能。
四、Docker-Compose操作命令
用法:
Define and run multi-container applications with Docker.Usage:
docker-compose [-f <arg>…] [–profile <name>…] [options] [–] [COMMAND] [ARGS…]
docker-compose -h|–help
1.docker-compose操作命令
官方所有指令
常用指令
指令 | 说明 |
up | 启动容器编排(前提是当前目录存在docker-compose.yml文件) |
down | 删除容器编排,适用于docker-compose.yml文件发生变更、或安装出错时的卸载重装 |
ps | 查看所有服务状态,类似于docker ps -a |
start | 启动服务 |
stop | 指定服务启动顺序,如存在多个服务nginx、db、Jenkins时,则在Jenkins服务下定义depends_on: db,会优先启动db服务 |
logs | 查看docker-compose操作日志 |
2.docker-compose操作参数
官方所有选项
常用选项
参数 | 说明 |
-f | 指定yml文件启动,当前目录下不存在docker-compose.yml文件时使用 |
-d | 后台运行 |
3.容器编排操作实践
启动容器编排
docker-compose up # 启动容器(前提是当前目录存在docker-compose.yml文件)
docker-compose -f docker-compose.yml up -d # 指定yml文件启动并设置后台运行
启动容器编排:创建网络>>创建并运行各个容器>>各个容器之间建立连接
在使用”docker-compose up”和”docker-compose down”命令时,若当前目录下不存在以下四种中的任一格式文件:docker-compose.yml, docker-compose.yaml, compose.yml, compose.yaml,或也未使用-f参数指定其他文件时,会报错提示:
删除容器编排
docker-compose down
删除容器编排:停止各个容器>>移除各个容器>>删除容器创建的网络
查看容器状态
docker-compose ps # 查看所有服务状态,类似于docker ps -a
启动服务
# docker-compose start 启动所有服务
# docker-compose start [SERVICE...] 启动指定服务
docker-compose start
停止服务
# docker-compose stop 停止所有服务
# docker-compose stop [options] [SERVICE...] 停止指定服务
docker-compose stop
与down命令不同,stop只会停止相关容器,但不会删除相关容器
查看日志
docker-compose logs
五、利用Docker Compose搭建wordpress博客系统
前面对一些常用指令作了说明,以及通过sonic前后台服务的docker-compose.yml案例对容器编排作了简单介绍,下面我们结合一个docker-compose搭建WordPress的案例来搭建我们自己的容器编排服务,官方配置文件内容如下:
1.配置docker-compose.yml
官网地址:https://docs.docker.com/compose/wordpress/
services:
db:
# We use a mariadb image which supports both amd64 & arm64 architecture
image: mariadb:10.6.4-focal
# If you really want to use MySQL, uncomment the following line
#image: mysql:8.0.27
command: '--default-authentication-plugin=mysql_native_password'
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
- MYSQL_ROOT_PASSWORD=somewordpress
- MYSQL_DATABASE=wordpress
- MYSQL_USER=wordpress
- MYSQL_PASSWORD=wordpress
expose:
- 3306
- 33060
wordpress:
image: wordpress:latest
volumes:
- wp_data:/var/www/html
ports:
- 88:80
restart: always
environment:
- WORDPRESS_DB_HOST=db
- WORDPRESS_DB_USER=wordpress
- WORDPRESS_DB_PASSWORD=wordpress
- WORDPRESS_DB_NAME=wordpress
volumes:
db_data:
wp_data:
【注意】
- 上述配置内容是可以自由修改的,并不一定要按照它的来,比如我本地就有MySQL,那就不需要再配置一个mysql或mariadb的容器
- yml文件中冒号后面要带空格,严格规范格式
2.查看容器状态
docker-compose ps -a
3.前端访问
启动docker-compose,各个容器处于up状态,此时就可以访问前端页面,http://192.168.1.123:88/,会先进行安装配置,如:设置数据库、站点取名
个人博客主页如下:
因为我是内网服务器,只能在局域网内访问,公网无法访问。如果你有一台带有公网的云服务器,如阿里云,那么妥妥的就可以搭建自己的个人网站了,这种对服务器要求不高,入门级的就可以。现在的云服务器都挺便宜,一年才几十块钱,像阿里云服务器个人用户可以免费体验一个月。关于WordPress详细搭建方法可以参考我前面介绍的《用2核2G的入门级云服务器搭建WordPress博客系统》
【docker 镜像仓库】
在前面的文章中,我们介绍了如何定制镜像、容器编排,但仿佛对镜像管理并没有提及,那么镜像文件我们是否可以像管理代码一样实现push、pull的操作呢?答案是有的,docker-hub就是一款公共仓库,在上面可以搜索到别人创建好的各种各样的镜像,以及管理自己的镜像;Harbor是一款私有化镜像仓库,我们可以把镜像上传上去,同一内网下的其他用户均可以下载使用,因为是部署在自己的服务器,因此对于安全性这方面更有保障。docker-hub和Harbor的关系我们可以类比成GitHub和Gitlab。
一、公共镜像仓库Docker-hub
1.docker-hub简介
公共镜像仓库一般是 Docker 官方或者其他第三方组织(阿里云,腾讯云,网易云等)提供的,允许所有人注册和使用的镜像仓库。Docker Hub 是全球最大的镜像市场,目前已经有超过 10w 个容器镜像。
2.提交镜像到仓库
具体步骤:注册账号>>登录>>创建仓库>>>linux命令行docker登录>>修改镜像名称(保持与仓库名称一致)>>提交镜像到仓库
① 创建镜像仓库
类似于github上创建代码仓库,分为public(公开的,互联网可见)和private(受保护的,尽自己可见)两种。
② Linux命令行登录Docker账号
docker login # 登录docker-hub
③ 修改镜像名称,保持与镜像仓库一致
docker tag joinsunsoft/docker.ui:latest chenjigang/auto-test:v1.1
④ 提交镜像到公共仓库
docker push chenjigang/auto-test:v1.1
⑤ 查看镜像仓库
二、私有化镜像仓库Harbor
1.Harbor简介
Harbor是由VMware公司开源的企业级的Docker Registry管理项目,它包括权限管理(RBAC)、LDAP、日志审核、管理界面、自我注册、镜像复制和中文支持等功能。
作为一个企业级私有 Registry 服务器,Harbor 提供了更好的性能和安全。提升用户使用 Registry 构建和运行环境传输镜像的效率。Harbor 支持安装在多个 Registry 节点的镜像资源复制,镜像全部保存在私有 Registry 中, 确保数据和知识产权在公司内部网络中管控。另外,Harbor 也提供了高级的安全特性,诸如用户管理,访问控制和活动审计等。
- 基于角色的访问控制 – 用户与 Docker 镜像仓库通过 “项目” 进行组织管理,一个用户可以对多个镜像仓库在同一命名空间(project)里有不同的权限。
- 镜像复制 – 镜像可以在多个 Registry 实例中复制(同步)。尤其适合于负载均衡,高可用,混合云和多云的场景。
- 图形化用户界面 – 用户可以通过浏览器来浏览,检索当前 Docker 镜像仓库,管理项目和命名空间。
- AD/LDAP 支持 – Harbor 可以集成企业内部已有的 AD/LDAP,用于鉴权认证管理。
- 审计管理 – 所有针对镜像仓库的操作都可以被记录追溯,用于审计管理。
- 国际化 – 已拥有英文、中文、德文、日文和俄文的本地化版本。更多的语言将会添加进来。
- RESTful API – RESTful API 提供给管理员对于 Harbor 更多的操控,使得与其它管理软件集成变得更容易。
- 部署简单 – 提供在线和离线两种安装工具, 也可以安装到 vSphere 平台 (OVA 方式) 虚拟设备。
gitee地址:https://gitee.com/project_harbor/harbor?utm_source=alading&utm_campaign=repo
2.Harbor搭建
安装说明: Harbor的所有服务组件都是在Docker中部署的,所以官方安装使用Docker-compose快速部署,所以需要安装 Docker、Docker-compose。由于Harbor是基于Docker Registry V2版本,所以就要求Docker版本不小于1.10.0, Docker-compose版本不小于1.6.0。
① 下载并解压安装包
在线下载:
wget https://github.com/goharbor/harbor/releases/download/v2.2.2/harbor-online-installer-v2.2.2.tgz
tar -xvf harbor-online-installer-v2.2.2.tgz
② 编辑配置文件
cp harbor.yml.tmpl harbor.yml # 复制一份harbor.yml文件
vi harbor.yml
按照如下内容编辑:
- hostname改为本机ip
- 端口默认80,可以改为其他指定端口
- 注释掉https的相关配置
③ 准备安装环境
./prepare # 执行prepare脚本
执行完成后,本地会多一个docker-compose.yml文件和common目录
④ 安装harbor
./install.sh # 安装harbor
安装过程中会自动下载harbor镜像并启动相关容器。
⑤ 访问harbor
安装成功后,即可访问harbor:http://192.168.1.122:8087,其中:ip为本机ip,端口为配置文件harbor.yml中配置的端口。默认账号和密码为:admin Harbor12345
harbor.yml文件中可查看或修改密码
⑥ 安装过程中常见问题及解决
- 报错redis容器重复
原因:本地已存在redis容器,harbor无法启动redis容器
解决办法:修改harbor目录下docker-compose.yml中的redis容器名称,重新启动
docker-compose up -d
查看harbor各个容器状态:
- 报错registry容器重复
若本地之前已存在registry容器时,harbor安装过程会报错,解决方案:删除原registry容器,重新执行./install.sh进行安装;若此方式仍报错,则执行docker-compose up -d启动各个服务;
3.推送本地镜像到Harbor
① 创建项目
② Docker登录
由于之前登录过docker-hub,所以再次使用“docker login”命令登录时,默认登录的还是docker-hub的地址。因此,如果想要登录harbor,需要在登录时指定登录地址。
docker login 192.168.1.122:8087
首次登录,根据提示输入harbor用户名及密码即可,与前端登录使用的账号密码一致。
由于我前面登录过一次这个地址,本地会保存认证记录,因此再次登录时无需输入用户名密码即可登录成功。
如遇以下报错:
则要在/etc/docker/daemon.json文件中将本机ip(端口非80时需要带上端口号)加入到insecure-registries列表中,并重载配置。
{
"registry-mirrors":[
"http://registry.docker-cn.com",
"http://docker.mirrors.ustc.edu.cn",
"http://hub-mirror.c.163.com",
"http://cr.console.aliyun.com/",
"https://8wb4g36l.mirror.aliyuncs.com"
],
"insecure-registries":["192.168.1.122:8087"],
"graph": "/home/docker_home"
}
systemctl daemon-reload
systectl restart docker
再次登录后登录成功:
③ 本地镜像打tag
镜像名称需要命名为:ip:端口号/项目名称/镜像名:tag名,才能上传到该指定项目下,例如rabbitmq镜像,则名称为:192.168.1.122:8087/harbor/rabbitmq:5.7.33
为了方便测试,我直接复制本地的一个镜像,并重新命名:
docker tag rabbitmq:3.7-management 192.168.1.122:8087/harbor/rabbitmq:3.7-management
④ 推送本地镜像到Harbor
docker push 192.168.1.122:8087/harbor/rabbitmq:3.7-management
查看名为harbor的项目下,存在rabbitmq:3.7-management,测试成功。
⑤ 从Harbor拉取镜像
- 拉取镜像
docker pull 192.168.1.122:8087/library/mysql:5.7.33
从下图可以看出,MySQL镜像已经拉取成功
同时,Harbor管理端也能看到最新的拉取时间:
- 创建容器
docker run -it -d -e MYSQL_ROOT_PASSWORD=123456 --name=mysql -p 3307:3306 192.168.1.122:8087/library/mysql:5.7.33
登录MySQL
【docker 可视化管理工具-DockerUI】
一、简介
DockerUI是一款开源的、强大的、轻量级的Docker管理工具。DockerUI覆盖了 docker cli 命令行 95% 以上的命令功能,通过可视化的界面,即使是不熟悉docker命令的用户也可以非常方便的进行Docker和Docker Swarm集群进行管理和维护。
DockerUI后端使用Go语言开发,前台框架使用CubeUI。通过Docker Restful API,经过Go语言编写的Proxy端, 实现和Docker Daemon进行通信,从而实现Docker的管理命令和维护命令。
官网:https ://github.com/gohutool/docker.ui
二、特征
- Docker主机管理管理 数据卷管理、镜像管理、容器管理、构建管理、仓库配置管理、网络配置管理
- Docker swarm集群管理 集群配置信息、节点管理、服务管理、任务管理、密码管理、配置管理
- 任务安排 Docker任务调度、docker swarm任务调度
三、安装
1.常规方式安装
1)下载docker.ui源码
git clone https://github.com/gohutool/docker.ui.git
2)安装golang运行环境
① 创建go文件夹
cd /home
mkdir go
② 下载go压缩包并解压缩
也可以通过wget命令下载:
wget https://golang.google.cn/dl/go1.19.1.linux-amd64.tar.gz
tar -xvf go1.19.1.linux-amd64.tar.gz
③ 添加到环境变量
编辑/etc/profile,添加如下内容:
export GO_HOME=/home/golang/go
export PATH=$PATH:$GO_HOME/bin
④ 重载环境变量
source /etc/profile
⑤ 验证是否安装成功
go --help
出现以下信息表示安装配置成功:
3)项目配置
进入docker.ui项目目录,执行以下命令
export GO111MODULE=on
export GOPROXY="https://goproxy.cn,direct"
go mod tidy
go mod download
go build -o server . # 执行完成后目录下会多出一个server文件
4)启动服务
./server
2.通过容器安装
1)拉取镜像
docker image pull joinsunsoft/docker.ui
2)创建容器
docker run --restart always --name docker.ui -d -v /home/docker_data/docker.ui/docker.sock:/var/run/docker.sock -p 8999:8999 joinsunsoft/docker.ui
3.浏览器访问
默认账号密码:ginghan 123456