Docker入门--师傅领进门

Docker简介

  • Docker 是一个开源的应用容器引擎,基于Go语言并遵从 Apache2.0 协议开源。

  • Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。

  • 容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。

Docker部署的优势

  • 通过使用Docker等容器技术,可以将应用程序及其依赖项打包成轻量级的容器,这个容器中包含了应用程序所需的所有运行环境和配置。这样一来,无论在测试还是生产环境中,都可以保证应用程序运行的一致性,并且易于部署扩展和管理。容器化技术使得应用程序在不同环境之间的迁移更加简单,并且可以高效地利用资源

Docker 中的名词概念

  • 在下面的Docker基础架构图中我们可以看出,Docker 在运行时分为 Docker 引擎和客户端工具。我们使用docker命令时,就是在使用客户端工具与Docker引擎进行交互。

  • 镜像 Image:镜像就是一个模板,docker通过这个模板创建多个容器提供相应的服务。

  • 容器 Container:容器可以理解成一个简易的Linux系统。docker利用容器技术可以独立运行一个或者一组应用,容器之间相互隔离互不影响。

  • 仓库 Repository:仓库是用来存放镜像的地方。

安装Docker

  • 每个系统安装的方式不同,搜索对应的教程即可,此处略过。

Docker基础命令

<container>名词解释

  • 参数 <container> 可以是容器 id名称

id格式为docker stop <container id>
名称格式为docker stop <container>

<container id>就是容器id,需要替换成自己的容器名。
<container>就是容器名,需要替换成自己的容器名。

查找docker镜像

  • 演示查找mysql数据库镜像(版本可选)

  • 格式为docker search mysql:8.0

docker search mysql
or
docker search mysql:8.0

拉取镜像

  • 演示拉取指定镜像的最后一个版本(最新版)

  • 格式为docker pull linuxserver/mysql:latest

#格式为 镜像提供方/镜像名:版本
docker pull linuxserver/mysql:latest

拉取镜像

  • 演示拉取指定镜像的指定版本

  • 格式为docker pull linuxserver/mysql:8.0

#格式为 镜像提供方/镜像名:版本
docker pull linuxserver/mysql:8.0

列出所有docker镜像

  • 查看系统内已拉取的所有docker镜像

docker images

删除docker镜像

  • 删除指定镜像

  • 格式为docker rmi mysql/mysql:8.0

docker rmi mysql/mysql:8.0

删除所有镜像

  • 删除所有没有在使用的docker镜像

docker rmi -f $(docker images -q)

列出所有docker容器

  • 查看当前系统内所有容器

docker ps -a

列出正在运行的docker容器

  • 列出正在运行的docker容器

docker ps

列出正在运行的容器 (带 CPU / 内存)

  • 列出正在运行的容器 (带 CPU / 内存)

docker ps -s

暂停容器运行

  • 将指定的某个容器暂停运行

  • 格式为docker pause <container>

  • <container>就是容器名,需要自己替换。

docker pause <container>

#演示
docker pause mysql

停止所有容器

  • 将运行中的所有容器关闭

docker stop $(docker ps -q)

取消暂停容器运行

  • 恢复暂停运行的某个容器,继续运行。

  • 格式为docker unpause <container>

  • <container>就是容器名,需要自己替换。

docker unpause <container>

#演示
docker unpause mysql

重启一个容器

  • 重启一个指定的容器

  • 格式为docker restart <container>

  • <container>就是容器名,需要自己替换。

docker restart <container>

#演示
docker restart mysql

停止容器运行

  • 停止指定的容器运行

  • 格式为docker stop <container>

  • <container>就是容器名,需要自己替换。

docker stop <container>

#演示
docker stop mysql

杀死一个容器

  • 将指定的容器强制关闭

  • 格式为docker kill <container>

  • <container>就是容器名,需要自己替换。

docker kill <container>

#演示
docker kill mysql

删除所有容器

  • 删除所有停止运行的容器

docker rm $(docker ps -aq) -f

显示容器的端口映射

  • 查看容器所使用的端口号

  • 格式为docker port <container>

  • <container>就是容器名,需要自己替换。

docker port <container>

#演示
docker port mysql

显示容器的控制台日志

  • 显示容器当前的日志

  • 格式为docker logs <container>

  • <container>就是容器名,需要自己替换。

  • Ctrl+C退出查看

docker logs <container>

#演示
docker logs mysql

阻塞容器

  • 阻塞运行直到容器停止运行,然后打印退出的代码。

  • 格式为docker logs <container>

  • <container>就是容器名,需要自己替换。

docker wait <container>

#演示
docker wait mysql

连接到现有容器(exec)

  • 启动一个新的进程进入容器正在执行的终端交互界面

  • 输入exit退出

docker exec -it <container/id> /bin/bash

#演示
docker exec -it mysql /bin/bash

连接到现有容器(attch)

  • 进入容器正在执行的终端交互界面,并且不会启动新的进程。

  • 输入exit退出,容器会停止运行。

  • 按Ctrl+P+Q退出,容器正常运行。

docker attach <container>

#演示
docker attach mysql

查看容器的元数据(详细信息)

  • 查看指定容器的详细信息

  • 格式为docker logs <container>

  • <container>就是容器名,需要自己替换。

docker inspect <container>

#演示
docker inspect mysql

获取服务器实时事件

  • 从服务器获取实时事件日志

  • 格式为docker logs <container>

  • <container>就是容器名,需要自己替换。

docker events <container>

#演示
docker events mysql

查看容器内部运行进程

  • 查看指定容器内部的实时进程情况

  • 格式为docker logs <container>

  • <container>就是容器名,需要自己替换。

docker top <container>

#演示
docker top mysql

查看容器资源使用情况

  • 查看指定容器占用的服务器资源

  • 格式为docker logs <container>

  • <container>就是容器名,需要自己替换。

docker stats <container>

#演示
docker stats mysql

列出对容器所做的更改

  • 用于比较一个 Docker容器 不同版本提交的文件差异

  • 格式为docker logs <container>

  • <container>就是容器名,需要自己替换。

docker diff <container>

#演示
docker diff mysql

查看容器卷

  • 查看指定容器所使用的卷

  • ERPNext14换成你自己想使用的容器名

docker inspect ERPNext14 | grep Source

#说明
docker inspect 容器名 | grep Source

Docker run命令参数

提示

  • 文中的参数基本都是简写

  • 在docker-compose部署方式上需要写完整的

  • 详细的可以看后面的部署模板

文中的参数基本都是简写

在docker-compose部署方式上需要写完整的

详细的可以看后面的部署模板

基础:创建一个新的容器并运行一个命令

  • docker最简单的方式就是docker run了。想要运行什么服务,就run相应的镜像。

  • 创建后直接进入容器交互界面,之后如果Ctrl+C退出则会连着容器一起挂起(暂停运行)。

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

#演示
使用nginx:latest镜像创建并运行一个名为mynginx的容器
docker run --name mynginx nginx:latest

-d: 后台运行容器,并返回容器ID

  • 以后台模式运行容器,即在容器创建成功并启动后在后台运行,并返回容器ID信息。

#使用docker镜像nginx:latest以后台模式启动一个容器,并将容器命名为mynginx。

docker run -d --name mynginx nginx:latest

--name: 为容器指定一个名称

  • 为创建的容器设置一个名称

  • 名称可以自己设置

  • 格式为:--name XXX

docker run -d --name mynginx nginx:latest

#说明
docker run:启动一个容器。
-d:后台模式运行容器
--name:设置容器名称为mynginx
nginx:latest:镜像来源:nginx:latest

-i: 以交互模式运行容器

  • 创建并启动容器后自动进入容器交互页面

  • 指示docker要在容器上打开一个标准的输入接口(控制台交互界面)

  • 通常与-t同时使用

docker run -i nginx:latest /bin/bash

#说明:
docker run:启动一个容器。
-i:以交互模式启动(进入容器中)
nginx:latest:镜像来源:nginx:latest
/bin/bash:进入容器后要执行的命令,这里是打开终端。
root@b8573233d675:/# :已经进入了容器里面的终端,用户名变化。

-t: 以交互模式(伪终端)运行容器

  • 创建并启动容器后自动进入容器交互页面

  • 为容器重新分配一个伪输入终端(控制台交互界面),通常与 -i 同时使用。

  • 组合使用方法为-it

docker run -it nginx:latest /bin/bash

#说明:
docker run:启动一个容器。
-it:以交互模式启动(进入容器中)
nginx:latest:镜像来源:nginx:latest
/bin/bash:进入容器后要执行的命令,这里是打开终端。
root@b8573233d675:/# :已经进入了容器里面的终端,用户名变化。

@小知识

  • 从本行开始

  • 需要几个参数就写几个参数

  • (仅限参数,如退出容器自动删除容器这中只需要一个即可。)

docker run -p 80:80 -p 90:90 -v /data:/data -d nginx:latest

#例如此条,有两个端口需要映射就添加两条-p端口映射参数

-p: 指定端口映射

  • 将容器内部的端口映射出来,映射到宿主机上。

  • 非常常用,从容器外访问容器内服务的主要方式。

  • 映射时要保证宿主机上没有占用需要映射的端口

  • 如果占用了就自己换一个或者调整

  • 格式为:主机(宿主)端口:容器端口

  • 访问时就是宿主机IP:容器映射的端口来访问容器内部的服务

docker run -d --name mynginx -p 8080:80 nginx:latest

#说明:
docker run:启动一个容器。
-d:以后台模式启动。
--name mynginx:将容器命名为mynginx。
-p 8080:80:将容器的 80 端口映射到主机的 8080 端口
nginx:latest:镜像来源:nginx:latest

--dns: 容器使用指定的DNS服务器IP

  • 设置容器使用指定的DNS服务器IP

  • 如果不添加此参数,那么默认的就是使用宿主机所使用的DNS

  • 格式为:--dns 8.8.8.8

docker run -d --name mynginx -p 8080:80 --dns 8.8.8.8 nginx:latest

#说明:
docker run:启动一个容器。
-d:以后台模式启动。
--name mynginx:将容器命名为mynginx。
-p 8080:80:将容器的 80 端口映射到主机的 8080 端口
--dns 8.8.8.8:设置容器使用指定的8.8.8.8DNS服务器IP
nginx:latest:镜像来源:nginx:latest

--rm:容器退出时自动删除容器

  • 常用于临时容器,在容器退出时自动删除容器。

docker run -it --rm ubuntu:14.04 bash

#说明:
docker run:启动一个容器。
-it:以交互式模式运行容器,进入容器终端界面。
--rm:设置此容器退出时自动删除此容器
ubuntu:14.04:镜像来源:ubuntu:14.04
bash:交互式Shell页面

-v:将主机的目录/文件挂载到容器中

  • --volume / -v: 绑定一个卷到容器中

  • 常用于容器数据持久化存储

  • 意思就是将宿主机指定的一个文件夹/文件挂载到容器内部指定的目录/文件上,这样容器内产生的数据就会存储在宿主机文件夹内,即便是容器删除了也不影响数据的留存。

docker run --name mynginx -p 8080:80 -v /volume1/data:/data -d nginx:latest、

#说明:
docker run:启动一个容器。
--name mynginx:将容器命名为mynginx。
-p 8080:80:将容器的 80 端口映射到主机的 8080 端口
-v /volume1/data:/data:将主机的目录 /volume1/data 映射到容器的 /data上
-d:以后台模式启动。
nginx:latest:镜像来源:nginx:latest

-e:设置容器环境变量

  • 设置容器的环境变量

  • 可以自定义修改容器的环境变量参数

  • 不同的环境变量需要参考容器所需参数

 docker run --name mysql \
  -p 3306:3306 \
  -v $HOME/mysql/conf.d:/etc/mysql/conf.d \
  -v $HOME/mysql/data:/var/lib/mysql \
  -v /etc/localtime:/etc/localtime:ro \
  -e MYSQL_ROOT_PASSWORD=123456 \
  -d mysql:5.7.23

#说明
-e MYSQL_ROOT_PASSWORD=123456 \这条参数的设置就是将MySQL数据库的密码设置为123456,此密码可以自己修改。

--env-file:从指定文件读取环境变量

  • 将容器的环境变量单独写在.env文件中

  • 添加参数从指定目录内的.env文件中读取环境变量参数

  • 常用于docker-compose方式部署容器

docker run -tid --env PATH=/volume1/docker/mysql/bin:$PATH --rm mysql:8.0

#说明
映射目录/volume1/docker/mysql/bin内的.env配置文件到容器

--link:连接到其他容器

  • 可以通过绑定所需要的容器

  • 通过容器名之间互相通信,容器间共享环境变量。

  • 主要用来解决两个容器通过IP地址连接时容器IP会变的问题

docker run -itd --name nginx01 --link tomcat01 nginx

#说明
以nginx镜像后台运行启动并进入交互式界面,创建nginx01容器,并与tomcat01容器连接,使其互相通信。

--privileged:以特权模式运行容器

  • 以特权模式运行容器,使该容器具备访问宿主机系统的权限,等于直接操作你的宿主机系统。

  • 使用--privileged参数会照成容器逃逸

  • 意思就是有概率有人攻破你的容器,再从你的容器内攻入你的宿主机系统。

  • 企业内谨慎使用,个人你怕个蛋。

docker run --privileged=true -it ubuntu

#说明
赋予ubuntu容器特权模式运行

--device:为容器添加指定访问权限

  • 为了系统安全,但是容器又必须使用宿主机上的设备访问权限

  • --device:此参数对容器进行授权宿主机的设备访问权限

  • 或者使用下面的参数

  • --cap-add:设置权限

  • --cap-drop:关闭权限

docker run --device=/dev/sda:/dev/xvdc -it ubuntu

或者

docker run --cap-add=NET_ADMIN -it ubuntu

--restart:重启策略

  • 为了保证容器运行时健壮性(自愈),Docker 提供了容器重启策略,即使用参数 --restart,它可以让容器在退出时自动尝试重启。

  • no:默认策略,在容器退出时不重启容器。启动容器时不添加参数 --restart 即可。

  • on-failure:在容器非正常退出时(退出状态非0),才会重启容器。

  • on-failure:n:在容器非正常退出时重启容器,并且指定重启次数。n 为正整数。如果不指定次数,则会一直重启。
    例如:on-failure:3

  • always:容器退出时总是重启。

  • unless-stopped:在容器退出时总是重启容器,但是 Docker 守护进程启动之前就已经停止运行的容器不算在内。

docker run -itd \
--name webos \
--restart=always \
-p 8088:8088 \
-v /:/webosMnt \
-v  /volume1/docker/webos/rootPath:/webos/api/rootPath \
-v /volume1/docker/webos/apps:/webos/web/apps \
fs185085781/webos

#说明
设置容器重启为always,只要容器退出了就自动重启。
  • 如果容器设置时忘记了设置重启策略可以使用下面的方法进行补救。

docker container update --restart=always [容器名/容器id]

#说明
将重启策略更新到指定的容器中

-c:限制容器对CPU的使用

  • -c--cpu-shares

  • -c:CPU权重

  • --cpu:CPU核数

  • -cpus: 限制容器运行的核数;从docker1.13版本之后,docker提供了--cpus参数可以限定容器能使用的CPU核数。这个功能可以让我们更精确地设置容器CPU使用量,是一种更容易理解也常用的手段。

  • --cpuset-cpus: 限制容器运行在指定的CPU核心; 运行容器运行在哪个CPU核心上,例如主机有4个CPU核心,CPU核心标识为0-3,我启动一台容器,只想让这台容器运行在标识0和3的两个CPU核心上,可以使用cpuset来指定。

# containerA的cpu share 1024, 是containerB 的两倍。
# 当两个容器都需要CPU资源时,containerA可以得到的CPU是containerB 的两倍。
# 需要特别注意的是,这种按权重分配CPU只会发生在CPU资源紧张的情况下。
# 如果containerA处于空闲状态,这时,为了充分利用CPU资源,containerB 也可以分配到全部可用的CPU。
docker run --name "cont_A" -c 1024 ubuntu docker run --name "cont_B" -c 512 ubuntu

# 容器最多可以使用主机上两个CPU ,除此之外,还可以指定如 1.5 之类的小数。
docker run -it --rm --cpus=2 centos /bin/bash

# 表示容器中的进程可以在 CPU-1 和 CPU-3 上执行。
docker run -it --cpuset-cpus="1,3" ubuntu:14.04 /bin/bash

# 表示容器中的进程可以在 CPU-0、CPU-1 及 CPU-2 上执行。
docker run -it --cpuset-cpus="0-2" ubuntu:14.04 /bin/bash

-m:限制容器对内存的使用

  • -m--memory:设置内存的使用限额,例如:100MB,2GB。

  • --memory-swap:设置内存+swap的使用限额。

  • 默认情况下,上面两组参数为-1,即对容器内存和swap的使用没有限制。如果在启动容器时,只指定-m而不指定--memory-swap, 那么--memory-swap默认为-m的两倍。

# 允许该容器最多使用200MB的内存和100MB 的swap。
docker run -m 200M --memory-swap=300M ubuntu


# 容器最多使用200M的内存和200M的Swap
docker run -it -m 200M ubuntu

--hostname:更改容器内的主机名

  • 在计算机中,hostname是指设备或机器的名称。在 docker 容器中,它也是一个标识符,用于标识容器。默认情况下,docker 容器的 hostname 是随机分配的,但是可以通过修改其值来自定义 hostname。

  • --hostname 标志只会更改容器内的主机名。如果你的应用程序需要主机名的特定值,则可能需要这样做。它不会更改 docker 之外的 DNS,也不会更改网络隔离,因此它不会允许其他人使用该名称连接到容器。

  • 可以使用容器名称或容器的(短,12 个字符)id 使用 docker 的嵌入式 dns 从容器连接到容器,只要您在同一网络上拥有两个容器并且该网络不是默认网桥。

docker run --hostname test --ip 10.1.2.3 ubuntu:14.04

#说明
创建一个 docker 容器,其基本映像为 ubuntu-14.04,主机名为 test,容器 ip 地址为 10.1.2.3
  • 说人话就是类似于ILO带外管理,输入ILO的主机名就可以连接到ILO登录页面,方便查找主机而已。

--add-host:为容器增加 host 指向

  • 例如安装jellyfin影视容器,为容器增加 host 指向,加速海报与影视元数据的搜刮。

  • 相关的host可以自己搜索/测试后添加进去。

  • 一行一个host进行添加

  • host格式:网站 优选IP

sudo docker run -d --name=Jellyfin -p 8096:8096 \  # --name=Jellyfin 将容器名定义为 Jellyfin 
	-p 8920:8920 -p 7359:7359/udp -p 1900:1900/udp #这三个端口为可选项 \
	-v /srv/jellyfin/config:/config -v /srv/jellyfin/cache:/cache -v /media:/media \
	-e TZ=Asia/Shanghai -e PUID=0 -e PGID=0 \	#将容器的时区设为上海,使用窗口在运行时使用root权限
	--device=/dev/dri:/dev/dri \	#直通显卡给 Docker 容器,用于硬解
	--add-host=api.themoviedb.org:13.224.161.90 \	#为容器增加 host 指向,加速海报与影视元数据的搜刮
	--add-host=api.themoviedb.org:13.35.8.65 \
	--restart unless-stopped \
	jellyfin/jellyfin:latest

--network:指定容器使用的网络类型

  • 指定容器的网络连接类型

  • 安装 Docker 以后,会默认创建三种网络,可以通过 docker network ls 命令查看。

  • 支持四种类型: bridge、host、none、container

  • bridge:为每个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,默认为该模式。
    (解释:最常用的是可以手动设置容器对外的端口,比如需要访问容器内的88端口,可以将容器内部88端口映射到宿主机的任意空闲端口上。)

  • host:容器不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。
    (解释:例如容器内部对外使用的88端口会自动映射到宿主机88端口上,如果宿主机88端口是被占用的,那么容器就会启动失败。)

  • none:容器独有的Network namespace,但没有对其进行任何网络设置,如分配veth pair和网桥连接、IP等。

  • container:新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。

Docker创建容器模板

简答创建容器

  • 模板中的参数需要多少个就加多少行对应的参数。不需要的可以删除。
    模板中的注释不要写进去

    docker run -d \    #前台运行容器不输入-d,后台运行输入-d,前台交互运行-i或-it,交互后台运行-itd。
        -p 9096:8096 \    #将容器的8096端口映射到主机的9096端口上
        -p 8888:88 \    #将容器的88端口映射到主机的8888端口上
        --name=S20306 \    #自定义容器名
        -v /volume1/docker/test:/mnt/test \    #将宿主机的/volume1/docker/test目录映射到容器/mnt/test目录
        -v /volume1/docker/config:/mnt/config \    #将宿主机的/volume1/docker/config目录映射到容器/mnt/config目录
        -v /var/run/docker.sock:/var/run/docker.sock \    #允许Docker CLI与Docker Daemon进行通信,从而实现对Docker容器的管理和控制。
        -e TZ=Asia/Shanghai \    #将容器的时区设为上海
        -e PUID=0 \    #约等于指定用户权限去运行容器,root用户是0,查看当前登录用户的数值SSH内输入id即可查看。
        -e PGID=0 \    #约等于指定用户权限去运行容器,root用户是0,查看当前登录用户的数值SSH内输入id即可查看。
        --add-host=api.themoviedb.org:13.224.161.90 \    #为容器增加 host 指向,加速海报与影视元数据的搜刮。
        --add-host=api.themoviedb.org:13.35.8.65 \    #为容器增加 host 指向,加速海报与影视元数据的搜刮。
        --device=/dev/dri:/dev/dri \    #直通核显给Docker容器,用于硬件解码。
        --privileged=true \    #设置容器使用特权模式,如果选择了--device参数就不用设置此行。
        --cpus=2 \    #设置此容器最多可以使用2个CPU核心运行
        -m=2G \    #设置此容器最多可以使用2GB内存运行
        --restart unless-stopped \    #设置容器自动重启
        --network=testnetwork \    #设置容器网络为host,如果选择了上面的-p端口映射,就不需要此行。如果是指定网络就需要提前创建好网络,格式为:--network=XXX
        --link nastool \    #通过容器名之间互相通信,容器间共享环境变量。
        jellyfin/jellyfin:latest    #选择镜像来源和版本
  • 如果是一行命令创建容器,就将\符号删除,改成一行命令即可。

    #只是演示,根据自己的需要添加参数即可。
    docker run --name reference -itd -p 9667:3000 wcjiang/reference:latest

Docker进阶命令

进入容器Bash交互页面

  1. 例如进入jellyfin容器的bash页面

    docker exec -it jellyfin /bin/bash
    
    #演示,进入之后就可以执行你的后续操作
    root@NAS:~# docker exec -it jellyfin /bin/bash
    root@2be7994cb319:/#
    

宿主机与容器直接拷贝文件

  1. 将jelyfin容器内根目录下的/jellyfin/wwwroot目录拷贝到主机的/volume1/docker目录下

    #格式:docker cp 容器名或容器id:/容器内的目录或文件 宿主机存放拷贝出来的文件的目录
    
    docker cp jellyfin:/jellyfin/wwwroot /volume1/docker
  2. 将宿主机/volume1/docker/wwwroot目录拷贝到jellyfin容器根目录下的/jellyfin目录内

    #格式为:docker cp 宿主机需要拷贝的文件或文件夹路径 容器名或容器id:存放所拷贝文件的路径
    
    docker cp /volume1/docker/wwwroot jellyfin:/jellyfin/