Docker 安装
下载: https://docs.docker.com/get-docker/
Win 10(家庭版)
需要安装Hyper-V才可以。将如下代码添加到记事本中,并另存为 Hyper-V.cmd 文件。右键以管理员身份运行,然后等待安装,最后输入 Y 进行重启即可
pushd "%~dp0"
dir /b %SystemRoot%\servicing\Packages\*Hyper-V*.mum >hyper-v.txt
for /f %%i in ('findstr /i .hyper-v.txt 2^>nul') do dism /online /norestart /add-package:"%SystemRoot%\servicing\Packages\%%i"
del hyper-v.txt
Dism /online /enable-feature /featurename:Microsoft-Hyper-V-All /LimitAccess /ALL
重启完后双击 docker 安装包安装,再次重启,启动 docker,可能提示 wsl 版本低,wsl --update
Win 10 (专业版)
启用Hyper-V进行安装:在控制面板—启用或关闭 Windows 功能,勾选Hyper-V和容器两个选项,两个都要,不然报错。然后重启,双击 exe 文件。
注意:如果使用安卓虚拟机的话,二者会有冲突。安卓虚拟机需要关闭 Hyper-V,docker 需要开启 Hyper-V。有文章说在控制面板—启用或关闭 Windows 功能—启用 Windows 虚拟机监控程序平台,勾选这个可以解决冲突,但我试了没有用。我用夜神模拟器有冲突,改用蓝叠 4 模拟器(hyper-v)版本

配置阿里云镜像: https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
修改默认位置:默认是在 C 盘
打开设置,选择存储位置

之前眼瞎没找见设置里的 Disk image location 选项,找了另一篇文章里的方法。
C:\Users\> wsl --list -v # 退出docker,用任务管理器杀进程
NAME STATE VERSION
* docker-desktop Stopped 2
docker-desktop-data Stopped 2
C:\Users\> wsl --export docker-desktop-data "D:\\docker-desktop-data.tar" # 将docker-desktop-data导出到文件中(备份image及相关文件)
正在导出,这可能需要几分钟时间。
操作成功完成。
C:\Users\> wsl --unregister docker-desktop-data # 从wsl取消注册docker-desktop-data
正在注销。
操作成功完成。
C:\Users\> wsl --import docker-desktop-data "E:\\DockerImage\\wsl" "D:\\docker-desktop-data.tar" --version 2 # 将导出的docker-desktop-data再导入回wsl,并设置我们想要的路径,即新的镜像及各种docker使用的文件的挂载目录,我这里设置到E:\\DockerImage\\wsl
参考: https://blog.csdn.net/u013948858/article/details/111464534
Debian 10
安装 Docker
1)直接使用脚本安装:
curl -sSL https://get.docker.com/ | sh
# 使用阿里镜像源
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
2)执行以下步骤从 Docker 的存储库安装最新的稳定 Docker 版本。root 用户下执行
apt update
# 安装通过 HTTPS 添加新存储库所需的软件包:
apt install apt-transport-https ca-certificates curl software-properties-common gnupg2
# 使用以下 curl 命令导入存储库的 GPG 密钥;成功后,命令将返回 OK 。
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
# 将稳定的 Docker APT 存储库添加到系统的软件存储库列表中:
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
# 更新 apt 软件包列表并安装最新版本的 Docker CE (Community Edition)
apt update
apt install docker-ce
使用阿里云存储库(推荐)
参考: https://help.aliyun.com/zh/ecs/use-cases/install-and-use-docker
这是 Debian 系统的命令,其他系统请查看文档
#更新包管理工具
sudo apt-get update
#添加Docker软件包源
sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common
sudo curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/debian/gpg | sudo apt-key add -
sudo add-apt-repository -y "deb [arch=$(dpkg --print-architecture)] https://mirrors.aliyun.com/docker-ce/linux/debian $(lsb_release -cs) stable"
#安装Docker社区版本,容器运行时containerd.io,以及Docker构建和Compose插件
sudo apt-get -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
#启动Docker
sudo systemctl start docker
#设置Docker守护进程在系统启动时自动启动
sudo systemctl enable docker
3)离线安装
因网络问题,导致 docker 无法联网安装,所以使用离线安装的方式。直接参考这个文章: https://blog.csdn.net/weixin_42571882/article/details/134015815
下载 docker 安装包: https://download.docker.com/linux/static/stable/x86_64/ ,网盘下载:docker-25.0.5.tgz
# 注意从网盘下载的文件后缀名为docker-25.0.5.tgz.zip,需要先改为docker-25.0.5.tgz
mv docker-25.0.5.tgz.zip docker-25.0.5.tgz # 改后缀
tar -zxvf docker-25.0.5.tgz # 解压docker安装包
cp docker/* /usr/bin/ # 将解压后的文件复制到/usr/bin/目录下
赋予文件执行权限
# 赋予文件执行权限,可以先赋予,在复制到/usr/bin/目录下
chmod +x /usr/bin/docker*
查看是否有执行权限
ls -l /usr/bin/docker*
将 docker 注册成系统服务
vim /etc/systemd/system/docker.service
添加如下内容,然后保存退出(我也不知道这些内容的具体含义,反正目前用着没问题)
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
赋予文件执行权限
chmod +x /etc/systemd/system/docker.service
systemctl daemon-reload
systemctl start docker
# 安装命令合集
wget http://oss.lanhuli.top/docker_files/docker-23.0.6.tgz && tar -xvf docker-23.0.6.tgz && chmod 755 ./docker/* && cp ./docker/* /usr/bin/ && wget http://oss.lanhuli.top/docker_files/docker-compose-2.17.0 && chmod 755 docker-compose-2.17.0 && mv docker-compose-2.17.0 /usr/local/bin/docker-compose && rm -rf docker && rm -rf docker-23.0.6.tgz
# 注册systemctl服务同上
查看安装的docker版本
apt list -a docker-ce
apt-cache madison docker-ce | awk '{ print $3 }' # 结果同上
修改 docker 的存储路径
方法一:使用软连接(个人常用)
# 查看现在的存储路径,默认是 /var/lib/docker
docker info | grep "Root Dir"
# 停止docker服务
systemctl stop docker
# 将这个目录复制到/opt目录下,名字任意
cp -r /var/lib/docker /opt/docker_images
# 删除原来的目录
rm -r /var/lib/docker
# 创建软链接
ln -s /opt/docker_images /var/lib/docker
# 记得重启docker或系统
systemctl start docker
方法二:修改配置文件
因为我这里没有 /etc/docker/daemon.json 这个文件,遂放弃。
安装 docker-compose
# 从github下载docker-compose二进制文件,这可能需要一段时间
curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 给予运行权限
chmod +x /usr/local/bin/docker-compose
# 查看安装版本
docker-compose -v
Docker 命令
批量处理命令
docker ps -a # 查看所有容器
docker ps -a -q # 查看所有容器ID
docker stop $(docker ps -a -q) # stop停止所有容器
docker rm $(docker ps -a -q) # remove删除所有容器
镜像仓库
login/logout
docker login -u 用户名 -p 密码 # 登陆到一个Docker镜像仓库,如果未指定镜像仓库地址,默认为官方仓库 Docker Hub
docker logout # 登出Docker Hub
search

参数说明:
NAME: 镜像仓库源的名称
DESCRIPTION: 镜像的描述
OFFICIAL: 是否 docker 官方发布
stars: 类似 Github 里面的 star,表示点赞、喜欢的意思。
AUTOMATED: 自动构建。
--automated :只列出 automated build类型的镜像;
--no-trunc :显示完整的镜像DESCRIPTION(描述),不省略;
-f <过滤条件>:列出收藏数(点赞)不小于指定值的镜像。
--limit 5:列出前5个镜像
build
docker build:用于使用 Dockerfile 创建镜像
--tag,-t:镜像的名字及标签
-f:指定要使用的 Dockerfile 路径
docker build -t bluelotus_xss_docker:2.0 .
docker build -f /path/to/a/Dockerfile .
注意:最后要加路径,这里最后有个空格和点,代表上下文路径。
说明:构建会在Docker后台守护进程(daemon)中执行,而不是 CLI 中。构建前,构建进程会将全部内容(递归)发送到守护进程。大多情况下,应该将一个空目录作为构建上下文环境,并将 Dockerfile 文件放在该目录下。
pull
语法:docker pull [OPTIONS] NAME[:TAG|@DIGEST]
OPTIONS 选项:
–all-tags, -a: 用于下载该存储库中具有不同标签的所有镜像。
–disable-content-trust: 它会在拉取之前跳过镜像验证。
–platform: 用于设置平台。
–quiet, -q: 用于静默拉取镜像(不冗长)。
–help: 了解更多有关命令的信息
docker pull citizenstig/dvwa # 默认tag是:latest,更多tag需要再hub中查看
docker pull mysql:5.7
docker pull centos:centos6.8
push
注意:发布镜像时,需要将 image 重新命名,命名格式应为: dockerhub 用户名/镜像名
docker tag bluelotus_xss_docker:1.0 bluefoxqaq/bluelotus_xss_docker:1.0
docker login -u admin -p 123456
docker push bluefoxqaq/bluelotus_xss_docker:1.0
本地镜像管理
images
docker images:列出本地镜像。
语法:docker images [OPTIONS] [REPOSITORY[: TAG]]
OPTIONS 说明:
- -a : 列出本地所有的镜像(含中间映像层,默认情况下,过滤掉中间映像层);
- --digests : 显示镜像的摘要信息;
- -f : 显示满足条件的镜像;
- --format : 指定返回值的模板文件;
- --no-trunc : 显示完整的镜像信息;
- -q : 只显示镜像 ID。
rmi
docker rmi : 删除本地一个或多个镜像。
语法:docker rmi [OPTIONS] IMAGE [IMAGE...]
OPTIONS 说明:
- -f : 强制删除
- --no-prune : 不移除该镜像的过程镜像,默认移除
例如:docker rmi -f runoob/ubuntu:v4
tag
docker tag:为本地镜像添加一个新的标签
docker tag bluelotus_xss_docker:1.0 bluefoxqaq/bluelotus_xss_docker:1.0

注意:它们是同一个镜像,只是别名不同而已。
inspect
docker inspect:获取镜像的详细信息,其中,包括创建者,各层的数字摘要等。
-f ,--format:指定返回值的模板文件。Go 模板格式化输出
docker inspect debian:12.5
# 查看镜像的操作系统架构(arm还是x86)
docker inspect --format='{{.Os}}/{{.Architecture}}' e6bce4a855e5
# 获取正在运行的容器dvwa的 IP
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' dvwa

save
docker save:将指定镜像保存成 tar 归档文件。
-o :输出到的文件。
# 例如
docker save -o my_ubuntu_v3.tar runoob/ubuntu:v3
docker save -o xss_platfrom_docker.tar 79bb31b88efb
load
docker load:导入使用 docker save 命令导出的镜像。
-i:指定导入的文件
-q:精简输出信息
docker load -i xss_platfrom_docker.tar
export 和 import 导出的是一个容器的快照, 不是镜像本身, 也就是说没有 layer。你的 dockerfile 里的 workdir, entrypoint 之类的所有东西都会丢失,commit 过的话也会丢失。快照文件将丢弃所有的历史记录和元数据信息(即仅保存容器当时的快照状态),而镜像存储文件将保存完整记录,体积也更大。
docker save 保存的是镜像(image),docker export 保存的是容器(container);docker load 用来载入镜像包,docker import 用来载入容器包,但两者都会恢复为镜像;docker load 不能对载入的镜像重命名,而 docker import 可以为镜像指定新名称。
容器操作
ps
docker ps : 列出容器
- -a : 显示所有的容器,包括未运行的。
- -f : 根据条件过滤显示的内容。
- --format : 指定返回值的模板文件。
- -l : 显示最近创建的容器。
- -n : 列出最近创建的 n 个容器。
- --no-trunc : 不截断输出。
- -q : 静默模式,只显示容器编号。
- -s : 显示总的文件大小。

常用示例
docker ps -n 3 # 显示最近创建的 3 个容器,包括所有状态
docker ps -s # 显示容器的大小
# 格式化输出
docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Status}}"
docker ps -s --format "table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Size}}"
docker ps -a -s --format "table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Size}}"
docker ps -a -s --format "table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Size}}\t{{.Ports}}"

可用的
参考: https://www.runoob.com/docker/docker-ps-command.html
run
docker run : 创建一个新的容器并运行一个命令
- -a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项;
- -d: 后台运行容器,并返回容器 ID;
- -i: 以交互模式运行容器,通常与 -t 同时使用;
- -P: 随机端口映射,容器内部端口随机映射到主机的端口
- -p: 指定端口映射,格式为:主机 (宿主) 端口: 容器端口
- -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
- --name="nginx-lb": 为容器指定一个名称;
- --dns 8.8.8.8: 指定容器使用的 DNS 服务器,默认和宿主一致;
- --dns-search example. com: 指定容器 DNS 搜索域名,默认和宿主一致;
- -h "mars": 指定容器的 hostname;
- -e username="ritchie": 设置环境变量;
- --env-file=[]: 从指定文件读入环境变量;
- --cpuset="0-2" or --cpuset="0,1,2": 绑定容器到指定 CPU 运行;
- -m : 设置容器使用内存最大值;
- --network="bridge": 指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型;
- **--link=[]: 添加链接到另一个容器;
- --expose=[]: 开放一个端口或一组端口;
- --volume , -v: 绑定一个卷
start/stop/restart
docker start:启动一个或多个已经被停止的容器(docker start container1 container2 container3)
docker stop:停止一个运行中的容器(docker stop container1 container2 container3)
docker restart:重启容器
exec
docker exec :在运行的容器中执行命令
- -d : 分离模式: 在后台运行
- -i : 即使没有附加也保持 STDIN 打开
- -t : 分配一个伪终端
- -u,--user:指定用户
例如:
$ docker exec -i -t mynginx /bin/bash # 在容器 mynginx 中开启一个交互模式的终端
$ docker exec -it 9df70f9a0714 /bin/bash # 9df70f9a0714 是容器 id
$ docker exec 9df70f9a0714 service nginx strart
$ docker exec -u www-data -it nextcloud ls # 用www-data用户执行命令
cp
docker cp : 用于容器与主机之间的数据拷贝。
语法:docker cp [OPTIONS] srcPath destPath
例如:
将主机/ www/runoob目录拷贝到容器 96f7f14e99ab 的/ www目录下 。
docker cp /www/runoob 96f7f14e99ab:/www/
将主机/ www/runoob目录拷贝到容器 96f7f14e99ab 中,目录重命名为 www 。
docker cp /www/runoob 96f7f14e99ab:/www
将容器 96f7f14e99ab 的/ www目录拷贝到主机的/tmp目录中 。
docker cp 96f7f14e99ab:/www /tmp/
rm
docker rm:删除一个或多个容器。
强制删除容器 db01、db02:docker rm -f db01 db02
update
docker update:更新一个或多个容器的配置
docker update --restart=always 容器 ID (或者容器名) # 容器开机自启
rename
将容器重命名
docker rename 原容器名称 新容器名称
logs
docker logs : 获取容器的日志
--since:显示某个开始时间的所有日志
-t:显示时间戳
--tail:仅列出最新 N 条容器日志
# 查看某时间之后最新的 100 条日志:
docker logs -t --since="2021-08-18T 11:46:37" --tail=100 CONTAINER_ID)
stats
docker stats:查看容器资源的使用情况,包括:CPU、内存、网络 I/O 等
- --all , -a:显示所有的容器,包括未运行的。
- --format:指定返回值的模板文件。
- --no-stream:展示当前状态就直接退出了,不再实时更新。
- --no-trunc:不截断输出。

- CONTAINER ID 与 NAME:容器 ID 与名称。
- CPU % 与 MEM %:容器使用的 CPU 和内存的百分比。
- MEM USAGE / LIMIT:容器正在使用的总内存,以及允许使用的内存总量。
- NET I/O:容器通过其网络接口发送和接收的数据量。
- BLOCK I/O:容器从主机上的块设备读取和写入的数据量。
- PIDs:容器创建的进程或线程数。
网络管理
查看容器 ip 地址:docker inspect 容器id
docker network create:创建一个 docker 局域网络
docker network create mynetwork # 随机网段
docker network create --subnet 172.16.7.0/24 mynetwork # 指定网段
docker network connnet:将某个容器连接到一个 docker 网络
docker network connect mynetwork nginx
docker network connect mynetwork 容器id
# 在 docker run 时配置网络信息
docker run --name mynginx --network mynetwork --network-alias nginx --ip 172.16.7.2 镜像id
# --network :加入 docker 内部网络
# --network-alias :配置容器在内部局域网的网络别名
# --ip:配置在内部局域网的 ip 地址 172.172.0.1 是网关
# 一个名为 mynginx 的容器,加入到 mynetwork 的网络当中,他的网络名为 nginx。
# 启动 Docker 容器的时候,使用默认的网络是不支持指派固定 IP 的
docker network disconnect:将某个容器退出某个局域网络
docker network ls:显示所有 docker 局域网络

docker network inspect:显示某个局域网络信息

docker network rm:删除 docker 网络
docker network prune:删除所有未引用的 docker 局域网络
数据卷容器管理
docker volume create <volume_name> # 创建数据卷
docker run -v <volume_name>:/home/data nginx # 将数据卷挂载到容器
docker volume ls # 查看数据卷
docker volume rm # 删除数据卷
docker volume inspect # 查看数据卷详情
docker volume prune # 删除未使用的数据卷
- 数据卷不存在时会自动创建
- 数据卷中没有文件时,会将容器目录中的文件挂载到数据卷中,数据卷中有文件时,会将数据卷中的文件覆盖容器目录中的文件
Docker-Compose
Docker-Compose 项目是 Docker 官方的开源项目,负责实现对 Docker 容器集群的快速编排。
安装
# 从 github 下载 docker-compose 二进制文件,这可能需要一段时间
curl -SL https://ghproxy.com/https://github.com/docker/compose/releases/download/v2.15.1/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
# 给予运行权限
chmod +x /usr/local/bin/docker-compose
# 查看安装版本
docker-compose -v
简单使用
docker-compose up :该命令可以自动完成包括构建镜像,(重新) 创建服务,启动服务,并关联服务相关容器的一系列操作。
默认情况下,docker-compose up 启动的容器都在前台,控制台将会同时打印所有容器的输出信息,可以很方便进行调试。当通过 Ctrl+c 停止命令时,所有容器将会停止。如果希望在后台启动并运行所有的容器,使用 docker-compose up -d。
docker-compose ps :列出项目中目前的所有容器
docker-compose pull :拉取服务依赖的镜像
docker-compose restart :重启项目中的服务
docker-compose start :启动已经存在的服务容器。
docker-compose stop :停止正在运行的容器,可以通过 docker-compose start 再次启动
docker-compose rm :删除所有(停止状态的)服务容器。选项包括: –f, –force,强制直接删除,包括非停止状态的容器 -v,删除容器所挂载的数据卷
注意:stop 是只停掉容器不删除;down 是停掉容器然后删除掉二者区别
docker-compose logs -f
yaml 文件编写说明
version: '3'
services:
webdav:
image: bytemark/webdav
restart: always
ports:
- "8880:80"
environment:
AUTH_TYPE: Digest
USERNAME: xujiajun
PASSWORD: xujiajun
volumes:
- /srv/dav:/var/lib/dav
docker run、create、start 命令区别
参考文章:docker中run、start和create命令的区别_allway2的博客-CSDN博客
docker create:从 Docker 映像创建一个全新的容器。但是,它不会立即运行它。
docker start:将启动任何已停止的容器。如果使用 docker create 命令创建容器,则可以使用此命令启动它。
docker run :是创建和启动的组合,因为它创建了一个新容器并立即启动它。实际上,如果 docker run 命令在您的系统上找不到上述映像,它甚至可以从 Docker Hub 中提取映像。docker run 只在第一次运行时使用
Docker 网络使用
Docker 容器运行的时候有 host、bridge、none 三种网络可供配置。默认是 bridge,即桥接网络,以桥接模式连接到宿主机;host 是宿主网络,即与宿主机共用网络;none 则表示无网络,容器将无法联网。
容器网络别名:容器在网络是是允许有别名的,且这个别名在所在网络中都可以直接访问,这就类似局域网在各物理机的主机名。
注意:必须创建一个自定义的网络,在这个网络里面,才可以使用别名
为什么默认的网卡不可以使用别名进行 IP 地址解析呢:用户自定义的网卡可以在容器之间提供自动的 DNS 解析,缺省的桥接网络上的容器只能通过 IP 地址互相访问,除非使用 --link 参数。在用户自定义的网卡上,容器直接可以通过名称或者别名相互解析。
docker 的 puid 和 pgid
参考: https://www.cnblogs.com/sparkdev/p/9614164.html
容器内的 root 用户和宿主机上的 root 用户是同一个。也就是说,docker 容器和宿主机内核共用一套 uid 和 gid 进行控制。
在 docker compose 的 yml 文件中指定 puid 和 pgid 为 1000,当这个容器创建运行的时候,进入容器里面。可以看到文件的所有者是用户 abc,他的 puid 值为 1000。

退出容器返回宿主机,查看 passwd 文件,查找 uid 为 1000 的用户。可以看到用户名为 share 123。使用 id 命令进行查看,它的 uid 为 1000,gid 为 100,表示当前工作组是 users, 其中 share 123 既是 users 组,又是 omv-share 组。

Dockerfile
Dockerfile 的指令是从上到下依次执行。其实跟我们直接敲命令差不多。
# 一些常见指令
FROM:指定基础镜像,必须
WORKDIR :设置指令的工作目录。不存在就创建。容器启动后,使用docker exec命令默认进入到这个目录下
COPY :将文件或目录复制到镜像中,第一个参数是宿主机文件,第二个是容器
RUN :镜像创建阶段中执行的命令
CMD :容器创建阶段中执行的命令,可以被覆盖。例如在 docker run 镜像 id xxxx 时
EXPOSE :声明端口号
# EXPOSE 只是声明,起到一个文档提示的作用,在运行 docker run 时可以用-p 参数指定端口映射,或者使用-P 参数,docker 会根据 EXPOSE 自动映射随机端口
RUN 和 CMD 的区别:RUN 是在创建镜像时执行的命令,一般是安装、下载、创建文件之类的。CMD 是在创建容器时才会执行的命令,一般是启动程序的命令。
CMD 两种写法
exec 模式:不会通过 shell 执行相关的命令,所以向 $HOME 这样的环境变量是获取不到的。
格式:CMD ["可执行文件","参数 1","参数 2"]
shell 模式:docker 以 /bin/sh -c command 的方式执行命令,也就是说容器的 1 号进程是 bash 进程。
格式:CMD command
例如:
CMD ["/bin/echo","hello"],会输出 hello。
CMD echo hello,也会输出 hello,但是他其实是这样的 CMD ["","-c","echo hello"]
CMD echo $HOME 实际执行是 CMD [ "sh", "-c", "echo $HOME" ]
推荐使用 exec 模式,如果命令太多可以写成一个脚本,然后运行这个脚本。
一个简单的 Dockerfile:安装 Nginx 并启动
# 需要一个 Debian 9.4 的镜像
FROM debian: 9.4
# 上传 apt 源配置
COPY ./sources.list /etc/apt/sources.list
# 安装 Nginx
RUN apt update ; apt install nginx -y
# 声明端口,仅仅只是一个声明,描述需要哪些端口
EXPOSE 80
#启动Nginx
COPY start_nginx.sh /root/start_nginx.sh
WORKDIR /root/
RUN chmod 777 /root/start_nginx.sh
CMD ["sh","-c","./start_nginx.sh"]
FROM debian: 9.4:指定一个基础镜像,需要一个 Debian 9.4 的镜像
COPY ./sources.list /etc/apt/sources.list:将宿主机的 ./sources.list 复制到容器的 /etc/apt/sources.list,这个 sources.list 文件,是提前准备好的 apt 源。
RUN apt update ; apt install nginx -y:执行两条命令,更新源和安装 Nginx,这里用了分隔符执行两个命令,也可以分开写,用两个 RUN。
COPY start_nginx.sh /root/start_nginx.sh:将 Nginx 启动脚本复制到容器。脚本内容在后面说。
WORKDIR /root/:来到容器的 /root/ 目录下,也就是存放 Nginx 启动脚本的目录。
RUN chmod 777 /root/start_nginx.sh:赋予 Nginx 启动脚本执行权限。
CMD ["sh","-c","./start_nginx.sh"]:运行脚本。
先看看启动脚本内容
#!/bin/sh
/usr/sbin/service nginx start
/bin/bash
这里需要了解一下 docker 的机制:
Docker 不是虚拟机,容器中的应用都应该以前台执行,而不是像虚拟机、物理机里面那样,用 systemd 去启动后台服务,容器内没有后台服务的概念。
docker 容器运行必须有一个前台进程,如果没有前台进程执行,容器认为空闲,就会自行退出。一般常见的启动参数是 docker run -dit centos /bin/bash,/bin/bash 就是一个前台进程,你也可以用 top 之类的命令。
使用 CMD service nginx start 命令作为容器启动命令的话,这个命令执行成功后就会退出,紧接着容器也会自动退出。对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出,其它辅助进程不是它需要关心的东西。
使用 service nginx start 命令,则是希望 upstart 来以后台守护进程形式启动 nginx 服务。而 CMD service nginx start 会被理解为 CMD [ "sh", "-c", "service nginx start"],因此主进程实际上是 sh。那么当 service nginx start 命令结束后,sh 也就结束了,sh 作为主进程退出了,自然就会令容器退出。
所以在启动脚本当中最后是 /bin/bash 命令。防止容器退出。也可以将 nginx 放到前台运行 CMD ["nginx", "-g", "daemon off;"]
注意:docker run xxxxxxxxxxxxx /bin/bash ,这里的/bin/bash 会覆盖掉 CMD 的命令。
查看容器大小
docker ps -s --format "table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Size}}"
# -s参数,显示容器大小
# --format "table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Size}}",格式化输出

SIZE 列,就是容器占用空间的大小,那这个括号外面的和里面的分别是什么意思
- 括号外面的,如:199MB. 表示现在向容器的可写层写入的数据量的大小。
- 括号里面的(virtual 313MB)。表示:镜像大小 + 可写层数据量大小之和。
容器大小 = 括号外面的 + 括号里面的
例如 python-oss 容器的大小为:199+313=512MB