【入门必读干货】我要成为Docker高手!从快速入门到落地部署,一篇就够了!
Docker是NAS的重要玩法之一,没有Docker的NAS莫得灵魂,就像西方不能没有耶路撒冷!
开始分享教程以来,发现不少小伙伴对于Docker并不太了解,有的甚至是一脸懵的状态~本篇旨在帮助咱们玩家快速掌握Docker基本用法,满足大部分需要,更好的玩转NAS!
某天某群的某位群友大成后:
篇幅较长,尽可能细;如果觉得不错,欢迎点赞收藏评论支持~有任何问题可留言/私聊
那么,什么是Docker?
Docker是一种快速构建、运行、管理应用的工具,简单来说就是帮助咱们去部署各种项目以及项目所需的各种组件,也可以看作是一个运维工具。
过去的项目,基本只能通过手动命令来操作Linux服务器,通过一些脚本来实现部署,还是比较复杂、麻烦(命令多、安装包多、安装步骤复杂)。在现在微服务盛行的当前,Docker为我们的效率带来极大提升,无需成为运维大师,也能轻松玩起来!
举个栗子
传统方式部署Nginx比较麻烦,大致需要以下步骤:
搜索并下载Nginx包体
上传至Linux服务器
编译及配置环境
安装
通过Docker部署则仅需一条命令完事儿:
docker run -d --name nginx -p 80:80 nginx
也可写成:
docker run -d
--name nginx
-p 80:80
nginx
本质也是一行命令,因为不够直观,所以用反斜杠 换行
复制粘贴再敲下回车键,即可全自动安装~
当然这里的命令行少了部分东西,放在后面说;但这种一键式部署方式,爽飞了有没有?
Docker 准备工作
想要体验Docker所带来的便利,首先要进行Docker的部署。很多情况下我们一般利用SSH工具连接服务器,通过命令行进行操作。
品牌NAS
这里以威联通为例,初始化系统后,打开App Center安装名为Container Station的应用程序(威联通的官方Docker图像化管理工具)
除去能更轻松管理Docker,Container Station也是商店内部分应用软件的安装前提。这是品牌NAS的一大好处,学习并了解Docker后,再有这玩意的加持,简直如虎添翼!
之后再开启SSH服务备用
云服务器(VPS)、Linux虚拟机等
这里以阿里云服务器为演示平台,操作系统为Debian_12_x64(个人使用推荐Debian/Ubuntu),其它Linux发行版大同小异。
一、更新软件包列表
输入以下命令并回车,等待包体安装更新:
apt update -y
这个命令可让系统的包管理器(APT)从配置的源中下载包的最新列表,以确保在安装新软件或更新现有软件时,能够获取到最新的版本。
二、安装常用软件包
输入以下命令:
apt install sudo vim git wget curl -y
日常用完全够。Red Hat、CentOS或Fedora等,需使用它们各自的包管理器,如yum或dnf来安装软件包。
三、安装Docker及Docker Compose
官方指引手册:https://docs.docker.com/engine/install
输入以下命令:
apt install docker -y # 安装docker
docker -v # 验证安装
systemctl enable docker # 设置docker开机自启
apt install docker-compose -y # 安装docker compose
docker-compose -v # 确认docker compose版本
四、配置镜像加速
看需求,若镜像下载速度很慢,可以进行配置。
以阿里云为例,提供一个免费的加速器地址,获取入口:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
可以看到官方已经给出现成命令
一条条复制进去执行即可
Docker 入门
首先是两个关键名词:image(镜像)、container(容器)
基础讲解
还是以Nginx为例,文章开头我们的部署命令如下:
docker run -d
--name nginx
-p 80:80
nginx
可以看到,我们回车执行命令后,Docker首先在本地搜索有无镜像,若没有则会去搜索并下载Nginx对应版本的镜像,然后自动运行它。
镜像中不仅包含了Nginx本体,还一并打包了它运行所需的环境、配置、系统函数库。
为了更直观理解镜像,不晓得大家是使用过绿色免安装版本的软件?某某软件园下载后解压后,也不用安装,进入文件夹找到并双击.exe
文件直接就能用,Docker也可近乎理解成此。
Docker在运行镜像时会为每一个应用创建一个隔离、独立环境,这个环境称为容器,这样可完美规避不同应用间的冲突,实现同设备下不同环境需求的多应用部署,或是某个应用的集群部署,保证服务平稳运行。
如图所示,部署多个Nginx,并且都成功启动
命令解读
根据Docker hub的官方文档,咱们把Nginx的命令进行完善
docker run -d
--name nginx
-p 80:80
-v /root/docker/data/nginx/html:/usr/share/nginx/html
-e TZ=Asia/Shanghai # 凑数的变量,方便演示
--network inter # 方便演示
nginx
docker run -d : 创建并运行一个容器,-d表示让容器以后台模式运行
--name nginx : 为容器命名,完全看个人喜好,但必须是唯一的
-p 80:80 : 设置端口映射
容器为隔离环境,外界不可访问。将容器的80端口映射到宿主机的80端口,这允许从宿主机访问容器内运行的服务。
容器内端口由容器内的进程决定,而宿主机端口则可以任意指定,例如-p 90:80
-p 宿主机端口:容器内端口,示例中就是将宿主机的80映射到容器内的80端口
-e TZ=Asia/Shanghai : 配置容器内进程运行时的一些参数,我们称为环境变量
格式:-e KEY=VALUE,KEY和VALUE都由容器内进程(作者)决定
TZ=Asia/Shanghai是设置时区;
官方文档可能包含必须变量和可选变量,部署前仔细阅读
--network inter : 定义容器的网络连接类型,这个咱们放在最后的网络部分讲
nginx : 设置镜像名称,Docker会根据这个名字搜索并下载镜像
格式:repository:tag,例如nginx:1.1,其中repository可以理解为镜像名,tag是版本号
在未指定TAG的情况下,默认是最新版本,也就是mysql:latest
以上为官方镜像格式,若想要拉取用户自建镜像,格式为username/my-custom-image:version,例如ydxian/nginx:1.1.0,通常ydxian/nginx也默认为最新版本
当然不同镜像由于作者配置不同,胡乱填写可能导致部署失败,还请阅读安装手册
Docker 常见命令
命令就是为了去操作镜像和容器,不过无需硬记忆,控制台可通过docker help快速查阅
所有命令见官方文档:https://b11et3un53m.feishu.cn/wiki/MWQIw4Zvhil0I5ktPHwcoqZdnec#YCejdEwpyo2hxRxpDx4cFFkDnQg
针对某个容器进行操作时,输入命令 容器名/容器ID前三位
即可,例如docker stop nginx
或docker stop 024
。下图为一些操作演示
数据卷
首先是一些常用命令https://docs.docker.com/reference/cli/docker/volume
无需死记硬背,控制台可通过docker volume help
查看
数据卷是什么
数据卷(volume)是一个虚拟目录,是容器内目录与宿主机目录之间映射的桥梁,与上面说过的端口(ports)有那么些类似。
咱们继续以Nginx为例,阅读官方文档可知Nginx有两个关键目录:
/usr/share/nginx/html
专门托管静态资源,/etc/nginx/nginx.conf
则负责保存配置文件。
那如果想对这两个部分进行配置,我们就得利用数据卷将两个目录与宿主机目录关联,方便操作
创建两个数据卷html
和conf
,Docker则会帮助我们为这两个数据卷在宿主机创建真实目录,位置为var/lib/docker/volums/html/_data
和var/lib/docker/volums/conf/_data
只要是在Linux系统下,var/lib/docker/volums
为默认位置,其下再根据数据卷名称创建新目录,格式为/数据卷名/_data
这样一来,容器内的html
和conf
便会通过两个数据卷与宿主机的对应目录相关联,这便是咱们常说的挂载。只要我们将静态资源放入宿主机对应目录,就可以被Nginx代理
根据上文,咱们重新对Nginx进行部署:
docker run -d --name nginx -p 80:80 -v html:/usr/share/nginx/html nginx
Web输入http://localhost:80
或http://host-ip:80
出现以下界面
接着进行演示
docker volume ls
# 列出所有数据卷,输出以下内容
*DRIVER VOLUME NAME
local html*
docker volume inspect html
# 显示数据卷html的详细信息,Mountpoint为宿主机挂载点
*[
{
"CreatedAt": "2024-04-09T13:41:08+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/html/_data",
"Name": "html",
"Options": null,
"Scope": "local"
}
]*
cd /var/lib/docker/volumes/html/_data
ls
# 列出静态资源文件,出现以下内容
*50x.html index.html*
cat index.html
# 查看 index.html 文件,所示内容即为我们web端看到的欢迎页面内容
也就是说/var/lib/docker/volumes/html/_data
与html
数据卷完成了映射,html
再与/usr/share/nginx/html
映射,最终就实现了/var/lib/docker/volumes/html/_data
与/usr/share/nginx/html
间的映射。
结合图片更为明显
为了更进一步进行验证,咱们对index.html
进行魔改,看看效果怎样。接着在这个目录下,输入以下命令:
vim index.html
修改后的代码如下,张大妈这边不能搞进html代码,就截图展示:修改了网站标题及欢迎页面文字,并将原本的网址替换成我的个人博客站
保存后退出,再刷新Web界面,结果符合预期
挂载
对于挂载,小伙伴们应该就很熟悉了吧!把上面的数据卷搞明白,那便是轻轻松松!
# 挂载命令格式,必须以 / 或 ./ 起始
-v 本地目录:容器目录
-v 本地文件:容器文件
# 举例,假设我们所在的宿主机目录为 /root/docker/data/nginx
-v html:/usr/share/nginx/html # 此处冒号左侧 html 会被识别成数据卷
-v ./html:/usr/share/nginx/html # ./ 表示当前目录下的 html 目录,若不存在,Docker会自动创建
-v /root/docker/data/nginx/html:/usr/share/nginx/html # 宿主机上的绝对路径,可将宿主机的静态数据直接提供给Nginx,也是最常用且方便的形式
那么我们为什么要把容器内目录挂载到指定的本地目录呢?原因有以下几点:
数据卷的目录机构较深,前面咱们也看到
/var/lib/docker/volumes/html/_data
这个目录又臭又长,每次操作起来非常麻烦!对于有些Docker项目,若不主动挂载,也会自动生成一个数据卷,一大串长字符那种
看看我威联通NAS自动生成的数据卷!
接下来进行演示,利用上文教程,咱们把nginx卸载重新安装,新增一条html挂载
mkdir -p /root/docker/data/nginx/html
docker run -d --name nginx -p 80:80 -v /root/docker/data/nginx/html:/usr/share/nginx/html nginx
# 此时我们若Web访问,会出现403报错,因为宿主机目录下为空,需要我们自行提供静态数据
cd /root/docker/data/nginx/html
ls
# 创建文件,把之前的拷贝进去并保存退出
vim index.html
ls
# 看到新建文件成功,此时再刷新Web界面,就可再次看到页面
操作流程图片展示
此时我们刷新Nginx界面,由于没有配置静态数据,页面403报错,但可以肯定的是Nginx已部署成功
通过指令配置静态数据,在原来基础上把YDXian
改成了QNAP
再次刷新界面
最后很重要的一点,如果我们挂载配置数据等文件,要提前准备好相应目录及文件;若未备好,执行命令后,Docker若找不到nginx.conf
文件,那仅会自动创建名为nginx.conf
的文件夹并报错
-v /root/docker/data/nginx/nginx.conf:/etc/nginx/nginx.conf
网络
网络嘛,顾名思义,咱们在命令解读部分稍微提到过。 常用类型有三种:bridge
、host
和自定义
;
Bridge:
为通常默认的网络类型,若不额外设置,容器会连接到这个网络。它是一个私有的内部网络,容器间可以互相通信,主机也可以与容器通信。
Host
移除容器和Docker主机之间的网络隔离,容器直接使用宿主机的IP地址和网络端口,这意味着不需要额外的端口映射。使用--network host
可以提高性能,并允许容器监听主机网络上的端口。例如大家都在用的Emby等流媒体服务。
自定义
对于咱们休闲玩家来说,基本不会这样做,如果容器间需要互相调用,若出现问题,可尝试选择此法。要事先命名并创建新网桥,例如docker network create inter
,再输入docker network connect inter 容器名
让其它加入。这样便可实现加入inter
网络的容器间相互访问,并支持直接通过容器名访问,无需知晓IP。
通过 docker inspect nginx ,可看到Nginx的IP地址为172.17.0.2
查看另一容器信息,IP地址为172.17.0.3
这就表示两个容器处在同一个网段,想一下咱们家里的局域网设备,同一路由器/交换机下的设备是不是也能够互相访问?
但有些疑惑,前面说过各个容器不是相互独立吗,为啥还能在同一网段?
细心的小伙伴可能已经发现,它们都有相同的网关172.17.0.1
,看过我之前教程分享的朋友,有没有觉得这个IP很熟悉?对的,我们做反向代理通常会填写这个IP!
其实在我们安装Docker那一刻起,它便会自动在设备中安装一个虚拟网卡docker 0
,并且还会为这个虚拟网卡创建一个虚拟网桥,用于容器与宿主机间的通信。它的地址为172.17.0.1/16
,172.17.0.1
是docker0
接口的IP地址,/16
表示子网掩码,定义了IP地址范围是172.17.0.0
到172.17.255.255
。
注:以上只是大多数情况,具体的IP地址范围可能会因安装和配置不同而有所变化。
关于自定义
,因使用场景不多,这里仅简单演示
docker network create inter # 创建名为inter的网络
network connect inter nginx # nginx加入inter
network connect inter emby # emby加入inter
可以看到,初始的Nginx多出了一个名为inter
的网络
若此法j解决不了,建议先使用docker logs 容器名
检查容器日志,了解错误详情;或使用docker exec -it 容器名 bash(或sh)
进入容器内部,然后使用curl或其它工具测试容器间的网络连接。
Docker Compose
docker compose可帮助我们实现多个相互关联的docker容器的快速部署,这是它的一大优势。
通过威联通官方docker管理工具Container Station用此种方式部署也是很舒服滴
粘贴进YAML
代码后,若指令有误,系统不会允许创建操作,根据提示排错完毕后才能进行创建。而且会进行提示,咱们逐一排错即可~下图中其实是environment
后少了个:
这便是品牌NAS的好处,面板高度可视化且便利性高!
笔者日常也更喜欢通过这种方式进行部署,基本语法可以参考官方文档:https://docs.docker.com/compose/compose-file/compose-file-v3
与Docker run对比
docker-compose文件中可以定义多个相互关联的应用容器,每一个应用容器被称为一个服务(service)。由于service就是在定义某个应用的运行时参数,因此与docker run
参数非常相似。
# docker run部署
docker run -d
--name nginx
-p 80:80
-e TZ=Asia/Shanghai
-v /root/docker/data/nginx/html:/usr/share/nginx/html
--restart=always
--network inter # 自定义网络
nginx
很多情况下部署失败是格式没对齐、漏空格、多/少符号导致
# docker compose部署
version: "3"
services:
nginx:
image: nginx
container_name: nginx
ports:
- "80:80"
environment:
- TZ=Asia/Shanghai
volumes:
- /root/docker/data/nginx/html:/usr/share/nginx/html
restart: always
networks: # 若为默认桥模式,从这往下全部删除
- news
networks:
news:
name: inter
常见对应表一览
大致部署流程
准备工作都差不多,如下
mkdir -p /root/docker/data/nginx # 创建nginx文件目录
cd /root/docker/data/nginx # 进入该目录下
mkdir html # 创建要挂载的宿主机目录
cd html # 进入html目录下
vim index.html # 准备静态数据文件,保存后退出
cd .. # 返回上级目录,回到nginx下
vim docker-compose.yml # 在nginx下创建 .yml 文件
# 将上面代码粘贴进去后保存并退出
docker-compose up -d # 启动
执行vim docker-compose.yml
后,如需编辑,英文状态下,按i
可进行编辑,编辑完成后,按Esc
返回正常模式,然后同时按下Shift
和:
,输入wq(写入并退出)
或:q!(不保存退出)
,按下回车键即可退出.
最后
其实大部分Docker应用的部署都不算难~基础知识原理了解差不多,部署前再多看看官方手册,很多答案都在那里,亲手操作个四五把就差不多咧!
祝大家玩的开心,咱们下期再见!
番外
来看个经典影音系统大合集,启动成功后,会得到四个部署完毕的容器。nastool库已经被删(作业应该可抄,请提前换库)
version: "3"
services:
jellyfin:
image: nyanmisaka/jellyfin:latest
container_name: jellyfin
environment:
- PUID=0
- PGID=0
- TZ=Asia/Shanghai
volumes:
- /share/Container/jellyfin/config:/config
- /share/media/video:/video
ports:
- 8096:8096
- 8920:8920
devices:
- /dev/dri:/dev/dri
nastool:
image: yohe/nastool:2.9.1
container_name: nastool
environment:
- PUID=0
- PGID=0
- TZ=Asia/Shanghai
- ALPINE_MIRROR=mirrors.ustc.edu.cn
- LANG=C.UTF-8
- NASTOOL_AUTO_UPDATE=false
- NASTOOL_CN_UPDATE=true
- NASTOOL_CONFIG=/config/config.yaml
- NASTOOL_VERSION=master
- PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
- PYPI_MIRROR=https://pypi.tuna.tsinghua.edu.cn/simple
- REPO_URL=https://github.com/jxxghp/nas-tools.git
- UMASK=000
- WORKDIR=/nas-tools
volumes:
- /share/Container/nastool/config:/config
- /share/media/video:/video
ports:
- 3000:3000
jackett:
image: linuxserver/jackett:latest
container_name: jackett
volumes:
- /share/Container/jackett/config:/config
- /share/Container/jackett/downloads:/downloads
environment:
- HOME=/root
- LSIO_FIRST_PARTY=true
- PATH=/lsiopy/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
- S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0
- S6_STAGE2_HOOK=/docker-mods
- S6_VERBOSITY=1
- TERM=xterm
- VIRTUAL_ENV=/lsiopy
- XDG_CONFIG_HOME=/config
- XDG_DATA_HOME=/config
ports:
- 9117:9117
qBittorrent:
image: linuxserver/qbittorrent:4.4.3
container_name: qBittorrent
volumes:
- /share/Container/qBittorrent/config:/config
- /share/media/video:/downloads
ports:
- 8080:8080
- 6881:6881
- 6881:6881/udp
博客网站搭建项目 Halo 2,官方提供代码,饭喂到嘴里系列
version: "3"
services:
halo:
image: halohub/halo:2.14
restart: on-failure:3
depends_on:
halodb:
condition: service_healthy
networks:
halo_network:
volumes:
- ./halo2:/root/.halo2
ports:
- "8090:8090"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8090/actuator/health/readiness"]
interval: 30s
timeout: 5s
retries: 5
start_period: 30s
command:
- --spring.r2dbc.url=r2dbc:pool:mysql://halodb:3306/halo
- --spring.r2dbc.username=root
# MySQL 的密码,请保证与下方 MYSQL_ROOT_PASSWORD 的变量值一致。
- --spring.r2dbc.password=mysal_secret
- --spring.sql.init.platform=mysql
# 外部访问地址,请根据实际需要修改
- --halo.external-url=https://blog.ydxian.love/
halodb:
image: mysql:8.1.0
restart: on-failure:3
networks:
halo_network:
command:
- --default-authentication-plugin=caching_sha2_password
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_general_ci
- --explicit_defaults_for_timestamp=true
volumes:
- ./mysql:/var/lib/mysql
- ./mysqlBackup:/data/mysqlBackup
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "--silent"]
interval: 3s
retries: 5
start_period: 30s
environment:
# 请修改此密码,并对应修改上方 Halo 服务的 SPRING_R2DBC_PASSWORD 变量值
- MYSQL_ROOT_PASSWORD=mysal_secret
- MYSQL_DATABASE=halo
networks:
halo_network:
加勒比考斯
校验提示文案
苦逼阿凯
校验提示文案
想去旅行
校验提示文案
Wayde_GO
校验提示文案
行走时光
校验提示文案
小射
校验提示文案
hanser
校验提示文案
温柔一刀007
校验提示文案
值友6402845458
校验提示文案
圖圖团
校验提示文案
苏莱蔓
校验提示文案
苏莱蔓
校验提示文案
圖圖团
校验提示文案
hanser
校验提示文案
值友6402845458
校验提示文案
小射
校验提示文案
行走时光
校验提示文案
温柔一刀007
校验提示文案
Wayde_GO
校验提示文案
想去旅行
校验提示文案
苦逼阿凯
校验提示文案
加勒比考斯
校验提示文案