Docker 像是一个容器一样,能够让应用运行在隔离的环境中。其实很像一个虚拟机,但是其本质和虚拟机是不同的,结构较虚拟机简单的多,因此速度也远快于虚拟机。
Docker 还是跨平台的,可以在 Linux/Windows/MacOS 上运行。
对于 Windows 的 Docker(准确的说是 Docker Desktop),它还提供了 Linux 和 Windows 两种子系统。(也就是说,在 Linux 下能运行的 Docker 容器,完全能够在 Windows 上运行)
而 Docker Compose 可以根据配置文件自动下载镜像、配置、运行 Docker 容器,一气呵成。
下载网上写好的配置文件,然后一行代码 docker-compose
即可完成配置,搭建好自己的云服务。它同样是跨平台的。这也是 Docker 方便的原因之一。
我收集的基于 Docker 的好用的云服务可以见后面小节。
# 安装、使用
# Linux 发行版安装
Debian/Ubuntu/Fedora/CentOS/RHEL 可使用清华源 (opens new window)安装。
Manjaro 直接走 sudo pacman -S docker
即可。
安装完成以后 docker ps
没有权限,可以把当前用户加到 docker
用户组:
sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker # log in to docker group
docker ps # 验证更改成功
# 加入阿里源
sudo wget -o /etc/docker/daemon.json https://blog.lyh543.cn/mirrors/docker.json
sudo systemctl restart docker.service
# 在 Docker Pull 时使用梯子
Cannot download Docker images behind a proxy - Stack Overflow (opens new window)
创建文件夹和配置文件:
sudo mkdir /etc/systemd/system/docker.service.d
sudo vim /etc/systemd/system/docker.service.d/http-proxy.conf
写入以下配置:
[Service]
Environment="HTTP_PROXY=http://localhost:17296/"
Environment="HTTPS_PROXY=http://localhost:17296/"
刷新并重启 docker
:
sudo systemctl daemon-reload
sudo systemctl restart docker
# 安装 docker-compose
sudo apt install docker-compose # debian
sudo pacman -S docker-compse # manjaro
# 在 WSL 1 中使用 docker-cli
WSL 2 中集成了 docker-cli,可以直接管理 Windows 的 Docker。在 WSL 1 中输入 docker
,可以看到 Docker 推荐你转换为 WSL 2。
The command 'docker' could not be found in this WSL 1 distro.
We recommend to convert this distro to WSL 2 and activate
the WSL integration in Docker Desktop settings.
See https://docs.docker.com/docker-for-windows/wsl/ for details.
然而我并不想转换,可参考 Windows 10 WSL1 的子系统下完美解决docker的命令问题_累积技术 沉淀经验-CSDN博客 (opens new window) 在 WSL1 下安装 docker-cli
。
# 常用 Docker 镜像
个人收集的一些基于 Docker 的云服务。
# 启动一个保持运行的 Ubuntu
这样在非 Linux 系统上就能有一个测试 Linux 的环境啦。
docker run -dit --name ubuntu --entrypoint '/bin/cat' ubuntu
# 云盘
镜像 | 创建命令或 docker-compose.yml 链接 |
---|---|
私人云 NextCloud | nextcloud-docker-compose.tar |
私人云 Seafile (opens new window) | docker-compse.yaml (opens new window) |
WebDAV | docker run -d --name webdav -v /srv/dav:/var/lib/dav -e AUTH_TYPE=Digest -e USERNAME=test -e PASSWORD=test -p 80:80 --restart always bytemark/webdav |
# 在线文档
镜像 | 创建命令或 docker-compose.yml 链接 |
---|---|
在线 Markdown 编辑器 CodiMD (opens new window) | docker-compse.yml (opens new window) |
在线 LaTeX 编辑器 Overleaf (opens new window) | docker-compose.yml (opens new window) |
# 数据库
镜像 | 创建命令或 docker-compose.yml 链接 |
---|---|
PostgreSQL | docker run -d --name postgres -p 5432:5432 -e POSTGRES_PASSWORD=test --restart always postgres |
MySQL | docker run -d --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=test --restart always mysql |
Redis | docker run -d --name redis -p 6379:6379 -e REDIS_PASSWORD=test --restart always redis /bin/sh -c 'redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}' |
Memcached | docker run -d --name memcached -p 11211:11211 --restart always memcached |
Hive | docker-compose.yml (opens new window) |
# 魔法
镜像 | 创建命令或 docker-compose.yml 链接 |
---|---|
shadowsocks (opens new window) | docker run -d --name shadowsocks -p 54285:54285 --restart always oddrationale/docker-shadowsocks -s 0.0.0.0 -p 54285 -k yourpasswd -m aes-256-cfb |
V2RayA 服务器端 (opens new window) | docker run -d --name v2ray -p 443:443 -p 80:80 -v $HOME/.caddy:/root/.caddy pengchujin/v2ray_ws:0.10 YOURDOMAIN.COM V2RAY_WS && sleep 3s && sudo docker logs v2ray |
V2RayA 客户端 (Linux) (opens new window) | docker run -d --restart=always --privileged --network=host --name v2raya -v /etc/v2raya:/etc/v2raya mzz2017/v2raya |
V2RayA 客户端 (MacOS) (opens new window) | docker run -d -p 2017:2017 -p 20170-20172:20170-20172 --restart=always --name v2raya -v /etc/v2raya:/etc/v2raya mzz2017/v2raya |
# 其他
镜像 | 创建命令或 docker-compose.yml 链接 |
---|---|
Docker Web 管理 | docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce |
Qbittorrent Enhanced Edition | docker run -d --name qbittorrentee -e WEBUIPORT=8081 -e PUID=1026 -e PGID=100 -e TZ=Asia/Shanghai -p 6881:6881 -p 6881:6881/udp -p 8081:8081 -v /media/Downloads:/downloads --restart always superng6/qbittorrentee |
云 SSH WebSSH2 (opens new window) | docker run -d --name webssh -p 2222:2222 oldiy/docker-webssh2 |
云 Firefox firefox-enpass-novnc (opens new window) | docker run -d --name firefox -p 8083:8083 -p 5900:5900 oldiy/firefox-enpass-novnc:latest |
# Docker 基础命令
初次接触 Docker,要记得两个概念:images(镜像) 和 containers(容器)。从网上获取一个镜像,然后每次可以由这个镜像创造一个容器(像是每次由一个系统镜像安装一个系统一样)。
下面是我最先接触到的几条命令,可能比较适合和我一样的新人。
命令 | 用途 | 常用参数 |
---|---|---|
docker run -dit ubuntu | 从 Ubuntu 镜像创造一个容器并运行 | 可用 --name 对容器命名,默认名是随机生成的;在最后可加 <command> |
docker start -i <name> | 运行名为 <name> (也可以是容器的 container ID 值的前几位)的容器 | |
docker images | 查看本地的镜像 | |
docker image prune -af | 删除所有没有使用的镜像(如果有容器使用了某镜像,无论这个容器正在运行/已停止,这个镜像不会被删除) | |
docker ps | 查看正在运行的容器 | 加 --all 或 -a 查看所有的(包括已停止的镜像) |
docker container rm <name> | 删除名为 <name> (也可以是容器的 container ID 值的前几位)的容器 | |
docker container prune -af | 删除所有已停止的容器 | |
docker container rename <old_name> <new_name> | 给容器改名 | |
docker exec -it <name> /bin/bash | 在正在运行的 <name> 容器中运行 bash 命令行 | |
docker update --restart=always <name> | 让 <name> 容器开机自启、自动重启 | |
-v ~/downloads:/var/webdav | 将容器外的 ~/downloads 映射到容器内的 /var/webdav | Windows 下将路径中 \ 改为 / 即可,如 d:/Downloads |
# Docker Compose 基础命令
命令 | 用途 | 常用参数 |
---|---|---|
docker-compose up | 以当前文件夹下的 docker-compose.yml 作为配置文件,run 一个容器 | -d 可在后台运行 |
docker-compose down -v | 删除当前文件夹下的 docker-compose.yml 所指的容器 |
# Docker 空间清理
参考:https://blog.fundebug.com/2018/01/10/how-to-clean-docker-disk/
使用 docker system df
查看 Docker 占了多少空间:
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 147 36 7.204GB 3.887GB (53%)
Containers 37 10 104.8MB 102.6MB (97%)
Local Volumes 3 3 1.421GB 0B (0%)
Build Cache 0B 0B
docker system prune
命令可以用于清理磁盘,删除关闭的容器、无用的数据卷和网络,以及 dangling 镜像(即无 tag 的镜像)。docker system prune -a
命令清理得更加彻底,可以将没有容器使用 Docker 镜像(包括暂时未用到的容器和镜像)都删掉。
如果你使用的是基于 Windows WSL 2 的 Docker,上面的操作只会释放 WSL 2 中的空间,WSL 2 占用 Windows 的空间并不会自动缩小。需要在管理员 PowerShell 下手动缩小 %LOCALAPPDATA%\Docker\wsl\data\ext4.vhdx
:
# 关闭 Docker
net stop com.docker.service
kill -Force -Name "docker", "Docker Desktop"
wsl --shutdown
# 缩小磁盘
Optimize-VHD -Mode Full -Path $Env:LOCALAPPDATA\Docker\wsl\data\ext4.vhdx
# 常见错误及解决办法
# 在 Docker 容器中如何安装软件
不少 Docker 容器都是采用的 Alpine Linux,这个 linux 发行版没有 sudo
,没有 bash
,我猜是为了简洁吧,毕竟要做成镜像,所以把没用的功能尽量都砍了。
Alpine Linux 下安装软件的命令为:
apk add <package name>
顺便中科大镜像源也有 Alpine Linux 的软件源,觉得国内网速慢的可以去更换,镜像站也有更换教程。
# Read-only file system
可能是 docker-compose.yml
中指定了目录为只读。这些可能出现在:
version: '3.3'
services:
redis:
image: redis:4.0.1-alpine
networks:
- myoverlay
read_only: true # 指定为只读
networks:
myoverlay:
web:
build: ./web
restart: always
ports:
- 7070:80
volumes:
# - nextcloud:/var/www/html:ro # ro 为只读 (read-only)
- nextcloud:/var/www/html # 可读写的版本
depends_on:
- app
# Container is unhealty
我在 Windows 下安装 overleaf 时,出现过下面的情况。
> docker-compose up
Creating network "overleaf_default" with the default driver
Creating overleaf_redis ... done
Creating overleaf_mongo ... done
ERROR: for sharelatex Container "233abaae4ea7" is unhealthy.
ERROR: Encountered errors while bringing up the project.
在配置文件 docker-compose.yml
中写到,sharelatex
基于 overleaf_redis
和 overleaf_mongo
,并且要求 mongo
是 healthy 的。
233abaae4ea7
正是我电脑上的 mongo
的 Container ID。
sharelatex:
depends_on:
mongo:
condition: service_healthy
redis:
condition: service_started
mongo:
healthcheck:
test: echo 'db.stats().ok' | mongo localhost:27017/test --quiet
interval: 10s
timeout: 10s
retries: 5
healthy 可以理解为是正常运行。
这里出错就有两种情况了,一是 mongo
本身不正常了,另一种是 mongo
检查的太频繁了,导致还没完成启动,就被诊断为 unhealthy 了。
我们检查一下 mongo 的 log。
> docker ps | find "233a"
233abaae4ea7 mongo "docker-entrypoint.s鈥? About a minute ago Restarting (14) 47 seconds ago overleaf_mongo
显示 mongo
正在重启,我估计是在反复不正常-重启,因此就考虑在这方面进行 debug。
最后的问题出在由于我是在 Windows 上运行,文件映射可能不正确,我把配置文件的 volumes
部分删掉就可以了。
当然,如果是正确的情况,上一行会显示:
> docker ps --all | find "mongo"
194bafd8158f mongo "docker-entrypoint.s鈥? 13 minutes ago Up 12 minutes (healthy) 27017/tcp overleaf_mongo
这种情况下,可以考虑把 mongo
的 healthcheck
部分的 inteval
和 timeout
调大。