2020-01-15 18:05:38 +08:00
|
|
|
|
---
|
|
|
|
|
layout: post
|
|
|
|
|
title: "Docker 安装和使用"
|
|
|
|
|
subtitle: ""
|
|
|
|
|
description: "包括 Docker 的基本概念和使用方法。"
|
|
|
|
|
excerpt: "本文描述了 Docker 的一些基本概念,并给出创建和启动容器的基本方法。"
|
2021-05-12 10:25:52 +08:00
|
|
|
|
date: 2021-05-12 09:24:00
|
2020-01-15 18:05:38 +08:00
|
|
|
|
author: "Rick Chan"
|
|
|
|
|
tags: ["Applications", "Docker"]
|
|
|
|
|
categories: ["Software"]
|
|
|
|
|
published: true
|
|
|
|
|
---
|
2019-12-18 22:04:25 +08:00
|
|
|
|
|
2023-05-06 10:40:32 +08:00
|
|
|
|
## 1. 安装
|
2019-12-18 22:04:25 +08:00
|
|
|
|
|
2020-05-20 16:18:39 +08:00
|
|
|
|
```bash
|
2019-12-19 11:47:06 +08:00
|
|
|
|
# Ubuntu
|
2022-03-11 09:48:33 +08:00
|
|
|
|
sudo apt install docker.io
|
2021-08-06 17:07:16 +08:00
|
|
|
|
# Manjaro
|
2022-03-11 09:48:33 +08:00
|
|
|
|
sudo pacman -S docker
|
2019-12-18 22:04:25 +08:00
|
|
|
|
```
|
|
|
|
|
|
2023-05-06 10:40:32 +08:00
|
|
|
|
## 2. 干掉讨厌的 sudo
|
2019-12-19 11:12:59 +08:00
|
|
|
|
|
2020-05-20 16:18:39 +08:00
|
|
|
|
```bash
|
2019-12-19 11:12:59 +08:00
|
|
|
|
# 如果还没有 docker group 就添加一个
|
|
|
|
|
sudo groupadd docker
|
|
|
|
|
# 将自己的登录名(${USER} )加入该 group 内。然后退出并重新登录就生效啦
|
|
|
|
|
sudo gpasswd -a ${USER} docker
|
|
|
|
|
# 重启 docker 服务
|
|
|
|
|
sudo systemctl restart docker
|
|
|
|
|
# 切换当前会话到新 group 或者重启 X 会话
|
|
|
|
|
# 注意,这一步是必须的,否则因为 groups 命令获取到的是缓存的组信息,刚添加的组信息未能生效,所以 docker images 执行时同样有错。
|
2020-02-13 16:15:34 +08:00
|
|
|
|
newgrp docker
|
2020-05-20 16:28:24 +08:00
|
|
|
|
# 或者
|
2019-12-19 11:12:59 +08:00
|
|
|
|
pkill X
|
|
|
|
|
```
|
|
|
|
|
|
2023-05-06 10:40:32 +08:00
|
|
|
|
## 3. 使用镜像源
|
2020-02-14 15:32:52 +08:00
|
|
|
|
|
|
|
|
|
以 USTC 镜像源为例。
|
|
|
|
|
|
2023-05-06 10:40:32 +08:00
|
|
|
|
### 3.1. 使用 upstart 的系统
|
2020-02-14 15:32:52 +08:00
|
|
|
|
|
|
|
|
|
在配置文件 /etc/default/docker 中的 DOCKER_OPTS 中配置 Hub 地址:
|
|
|
|
|
|
2020-05-20 16:18:39 +08:00
|
|
|
|
```ini
|
2020-02-14 15:32:52 +08:00
|
|
|
|
DOCKER_OPTS="--registry-mirror=https://docker.mirrors.ustc.edu.cn/"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
重新启动服务:
|
|
|
|
|
|
2020-05-20 16:18:39 +08:00
|
|
|
|
```bash
|
2020-02-14 15:32:52 +08:00
|
|
|
|
sudo service docker restart
|
|
|
|
|
```
|
|
|
|
|
|
2023-05-06 10:40:32 +08:00
|
|
|
|
### 3.2. 使用 systemd 的系统
|
2020-02-14 15:32:52 +08:00
|
|
|
|
|
|
|
|
|
在 /etc/docker 下创建 daemon.json 文件,修改其内容并重启启动 docker 相关服务:
|
|
|
|
|
|
2020-05-20 16:18:39 +08:00
|
|
|
|
```bash
|
2020-02-14 15:32:52 +08:00
|
|
|
|
cd /etc/docker
|
|
|
|
|
sudo touch daemon.json
|
|
|
|
|
sudo tee /etc/docker/daemon.json <<-'EOF'
|
|
|
|
|
{
|
|
|
|
|
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn/"]
|
|
|
|
|
}
|
|
|
|
|
EOF
|
|
|
|
|
sudo systemctl daemon-reload
|
|
|
|
|
sudo systemctl restart docker
|
|
|
|
|
```
|
|
|
|
|
|
2023-05-06 10:40:32 +08:00
|
|
|
|
## 4. 基本使用
|
2019-12-18 22:04:25 +08:00
|
|
|
|
|
2020-01-02 17:49:56 +08:00
|
|
|
|
Docker 的主要管理对象是镜像和容器,镜像是静态对象,保存了分层的用户数据;而容器是动态对象,可以看作镜像的运行状态,容器主要包容了 root fs。二者的关系如同程序文件与进程的关系。必须使用镜像来创建容器,一旦 Docker 加载并运行了某镜像,就为之创建一个与之对应的容器,容器至少有 stop 和 run 两个状态。使用 run 命令通过镜像创建容器后,该容器处于 run 状态,使用 exit 命令脱离容器后,容器处于 stop 状态。可以使用 start 命令将处于 stop 状态的容器再次运行起来。
|
2019-12-20 10:43:04 +08:00
|
|
|
|
|
|
|
|
|
如果每次都使用 run 命令从同一个镜像创建容器,会发现两个容器是完全一样的,因为他们都有相同的起始点。容器使用后,会保存当前的使用状态,但如果希望将其当前状态保存成镜像,可以使用 commit 命令。
|
|
|
|
|
|
2020-05-20 16:28:24 +08:00
|
|
|
|
*注意:以下 image name 为 \<repository\>:\<tag\> 这种形式。*
|
2019-12-20 10:43:04 +08:00
|
|
|
|
|
2020-02-14 15:32:52 +08:00
|
|
|
|
*建议先配置使用镜像源。*
|
|
|
|
|
|
2019-12-20 10:43:04 +08:00
|
|
|
|
以下是使用 Docker 的一些基础命令:
|
|
|
|
|
|
2020-05-20 16:18:39 +08:00
|
|
|
|
```bash
|
2020-04-27 13:46:50 +08:00
|
|
|
|
# 从 docker hub 上搜索镜像
|
|
|
|
|
docker search [option] <keyword>
|
2019-12-19 12:01:11 +08:00
|
|
|
|
# 从 https://hub.docker.com 拉取镜像
|
2021-05-20 16:07:39 +08:00
|
|
|
|
docker pull <name>[:tag]
|
2020-01-02 17:49:56 +08:00
|
|
|
|
# 运行某镜像并为之创建容器
|
2019-12-20 10:43:04 +08:00
|
|
|
|
docker run <image name/id>
|
2020-01-02 17:49:56 +08:00
|
|
|
|
# 运行某镜像,为之创建容器,将宿主机端口影射到容器端口,并将宿主机的某目录挂载到容器的对应目录下
|
2023-10-05 11:25:40 +08:00
|
|
|
|
docker run -it -p <host ip:port>:<container port> -v <host dir>:<container dir> <image name/id> /bin/bash
|
2020-05-13 10:59:41 +08:00
|
|
|
|
# 运行某镜像,为之创建容器,随机映射主机端口和容器端口,指定容器名称,赋予 privileged 权限,并将宿主机的某目录挂载到容器的对应目录下
|
|
|
|
|
docker run -it -P --name=<a container name> --privileged -v <host dir>:<container dir> <image name/id> /bin/bash
|
2020-01-02 17:49:56 +08:00
|
|
|
|
# 运行某镜像,为之创建容器,设置网络参数,并将宿主机的某目录挂载到容器的对应目录下
|
2021-07-26 18:12:30 +08:00
|
|
|
|
docker run -it --net=<bridge/host/container:container name or id/none> -v <host dir>:<container dir> <image name/id> /bin/bash
|
2020-08-21 17:29:10 +08:00
|
|
|
|
# 允许容器访问 usb 总线,允许容器通过 adb 连接 android 设备
|
|
|
|
|
docker run -it -P --name=<a container name> --privileged -v /dev/bus/usb:/dev/bus/usb <image name/id> /bin/bash
|
2021-06-04 15:27:33 +08:00
|
|
|
|
# 映射 Nvidia GPU
|
|
|
|
|
docker run -it -P --name=<a container name> --privileged --device /dev/nvidia0:/dev/nvidia0 <image name/id> /bin/bash
|
2021-11-17 04:22:17 +08:00
|
|
|
|
# 退出并关闭容器:在容器的 shell 中直接
|
|
|
|
|
exit
|
2019-12-18 22:04:25 +08:00
|
|
|
|
# 查看正在运行的容器
|
|
|
|
|
docker ps
|
2020-01-02 17:49:56 +08:00
|
|
|
|
# 提交针对某容器的修改,将其保存为镜像
|
2023-10-05 11:25:40 +08:00
|
|
|
|
docker commit <container name/id> <repository>:<tag>
|
2020-01-02 17:49:56 +08:00
|
|
|
|
# 运行某已存在的容器
|
2023-10-05 11:25:40 +08:00
|
|
|
|
docker start <container name/id>
|
2021-05-18 09:31:01 +08:00
|
|
|
|
# 连接到已运行的容器上
|
2023-10-05 11:25:40 +08:00
|
|
|
|
docker attach <container name/id>
|
2021-05-18 09:31:01 +08:00
|
|
|
|
# 运行并连接到已存在的容器上
|
2023-10-05 11:25:40 +08:00
|
|
|
|
docker start -a <container name/id>
|
2020-01-02 17:49:56 +08:00
|
|
|
|
# 在某已运行的容器中执行命令
|
2019-12-20 10:43:04 +08:00
|
|
|
|
docker exec -it <container name/id> <cmd and args>
|
2019-12-19 11:19:55 +08:00
|
|
|
|
# 迁移镜像
|
2019-12-19 11:12:59 +08:00
|
|
|
|
docker save -o <tar file> <image name/id>
|
|
|
|
|
docker load -i <tar file>
|
2019-12-19 11:19:55 +08:00
|
|
|
|
# 迁移容器
|
|
|
|
|
docker export -o <tar file> <container name/id>
|
2019-12-20 10:43:04 +08:00
|
|
|
|
docker import <tar file> <repository>:<tag>
|
2019-12-18 22:04:25 +08:00
|
|
|
|
```
|
|
|
|
|
|
2020-01-06 13:27:01 +08:00
|
|
|
|
想要退出但不关闭容器,在容器中按下 Ctrl + P + Q 组合健即可.
|
|
|
|
|
|
2023-05-06 10:40:32 +08:00
|
|
|
|
### 4.1. 容器操作
|
2019-12-18 22:04:25 +08:00
|
|
|
|
|
2020-05-20 16:18:39 +08:00
|
|
|
|
```bash
|
2019-12-18 22:04:25 +08:00
|
|
|
|
# 获得容器信息
|
|
|
|
|
docker container ls -a
|
|
|
|
|
# 获得容器id
|
|
|
|
|
docker container ls -a -p
|
|
|
|
|
# 停止容器
|
2023-10-05 11:25:40 +08:00
|
|
|
|
docker container stop <container name/id>
|
2019-12-18 22:04:25 +08:00
|
|
|
|
# 删除容器
|
2023-10-05 11:25:40 +08:00
|
|
|
|
docker container rm <container name/id>
|
2020-06-30 17:33:06 +08:00
|
|
|
|
# 重命名容器
|
2020-06-30 17:37:45 +08:00
|
|
|
|
docker container rename <current name> <new name>
|
2023-10-05 11:25:40 +08:00
|
|
|
|
# 更新容器的环境变量
|
|
|
|
|
docker container update --env <MY_VAR>=<value> <container name/id>
|
|
|
|
|
# 更新容器的端口映射
|
|
|
|
|
docker container update --publish <host port>:<container port> <container name/id>
|
|
|
|
|
# 更新容器的内存限制
|
|
|
|
|
docker container update --memory 512m <container name/id>
|
|
|
|
|
# 更新容器的 CPU 共享限制
|
|
|
|
|
docker container update --cpu-shares 512 <container name/id>
|
2019-12-18 22:04:25 +08:00
|
|
|
|
```
|
|
|
|
|
|
2023-05-06 10:40:32 +08:00
|
|
|
|
### 4.2. 镜像操作
|
2019-12-18 22:04:25 +08:00
|
|
|
|
|
2020-05-20 16:18:39 +08:00
|
|
|
|
```bash
|
2019-12-18 22:04:25 +08:00
|
|
|
|
# 获得镜像信息
|
|
|
|
|
docker image ls -a
|
|
|
|
|
# 获得镜像id
|
|
|
|
|
docker image ls -a -p
|
2019-12-19 11:43:20 +08:00
|
|
|
|
# 重命名镜像
|
|
|
|
|
docker tag <image name/id> <repository>:<tag>
|
2019-12-18 22:04:25 +08:00
|
|
|
|
# 删除镜像
|
|
|
|
|
docker image rm <image name/id>
|
|
|
|
|
```
|
2020-01-02 17:56:31 +08:00
|
|
|
|
|
2023-05-06 10:40:32 +08:00
|
|
|
|
## 5. 网络模式说明
|
2020-01-02 17:56:31 +08:00
|
|
|
|
|
2023-05-06 10:40:32 +08:00
|
|
|
|
### 5.1. bridge 模式
|
2020-01-02 17:56:31 +08:00
|
|
|
|
|
|
|
|
|
Docker 容器默认使用 bridge 模式的网络。其特点如下:
|
|
|
|
|
|
|
|
|
|
* 使用一个 linux bridge,默认为 docker0
|
|
|
|
|
* 使用 veth 对,一头在容器的网络 namespace 中,一头在 docker0 上
|
2022-02-22 10:47:28 +08:00
|
|
|
|
* 该模式下 Docker Container 不具有一个公有 IP,因为宿主机的IP地址与 veth pair 的 IP 地址不在同一个网段内
|
|
|
|
|
* Docker 采用 NAT 方式,将容器内部的服务监听的端口与宿主机的某一个端口 port 进行“绑定”,使得宿主机以外的世界可以主动将网络报文发送至容器内部
|
2020-01-02 17:56:31 +08:00
|
|
|
|
* 外界访问容器内的服务时,需要访问宿主机的 IP 以及宿主机的端口 port
|
|
|
|
|
* NAT 模式由于是在三层网络上的实现手段,故肯定会影响网络的传输效率。
|
2022-02-22 10:47:28 +08:00
|
|
|
|
* 容器拥有独立、隔离的网络栈;让容器和宿主机以外的世界通过 NAT 建立通信。
|
2020-01-02 17:56:31 +08:00
|
|
|
|
|
2023-05-06 10:40:32 +08:00
|
|
|
|
### 5.2. host 模式
|
2020-01-02 17:56:31 +08:00
|
|
|
|
|
2022-02-22 10:47:28 +08:00
|
|
|
|
Host 模式并没有为容器创建一个隔离的网络环境。而之所以称之为 host 模式,是因为该模式下的 Docker 容器会和 host 宿主机共享同一个网络 namespace,故 Docker Container 可以和宿主机一样,使用宿主机的 eth0,实现和外界的通信。换言之,Docker Container 的 IP 地址即为宿主机 eth0 的 IP 地址。其特点包括:
|
2020-01-02 17:56:31 +08:00
|
|
|
|
|
|
|
|
|
* 这种模式下的容器没有隔离的 network namespace
|
|
|
|
|
* 容器的 IP 地址同 Docker host 的 IP 地址
|
|
|
|
|
* 需要注意容器中服务的端口号不能与 Docker host 上已经使用的端口号相冲突
|
|
|
|
|
* host 模式能够和其它模式共存
|
|
|
|
|
|
2023-05-06 10:40:32 +08:00
|
|
|
|
### 5.3. container 模式
|
2020-01-02 17:56:31 +08:00
|
|
|
|
|
|
|
|
|
Container 网络模式是 Docker 中一种较为特别的网络的模式。处于这个模式下的 Docker 容器会共享其他容器的网络环境,因此,至少这两个容器之间不存在网络隔离,而这两个容器又与宿主机以及除此之外其他的容器存在网络隔离。
|
|
|
|
|
|
2023-05-06 10:40:32 +08:00
|
|
|
|
### 5.4. none 模式
|
2020-01-02 17:56:31 +08:00
|
|
|
|
|
2022-02-22 10:47:28 +08:00
|
|
|
|
网络模式为 none,即不为 Docker 容器构造任何网络环境。一旦 Docker 容器采用了none 网络模式,那么容器内部就只能使用 loopback 网络设备,不会再有其他的网络资源。Docker Container 的 none 网络模式意味着不给该容器创建任何网络环境,容器只能使用 127.0.0.1 的本机网络。
|
2021-05-12 10:25:52 +08:00
|
|
|
|
|
2023-05-06 10:40:32 +08:00
|
|
|
|
## 6. 查看 Docker run 启动参数
|
2021-05-12 10:25:52 +08:00
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
pip install runlike
|
|
|
|
|
runlike -p <container name/id>
|
|
|
|
|
```
|
2021-06-04 15:27:33 +08:00
|
|
|
|
|
2023-05-06 10:40:32 +08:00
|
|
|
|
## 7. 设置容器自启动
|
|
|
|
|
|
|
|
|
|
1. 使用 docker run 命令运行时增加 --restart=always 参数即可;
|
|
|
|
|
2. 使用 docker-compose 命令运行时在 yml 文件中,需要自启动的 service 下增加 restart: always 项目即可;
|
|
|
|
|
3. 已运行的容器修改其自启动策略,执行命令:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
docker container update --restart=<no|on-failure|always> <container name/id>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 8. 常用镜像
|
2021-06-04 15:27:33 +08:00
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
# Ubuntu
|
|
|
|
|
docker pull ubuntu:16.04
|
|
|
|
|
docker pull ubuntu:18.04
|
|
|
|
|
docker pull ubuntu:20.04
|
|
|
|
|
# Nvidia CUDA
|
|
|
|
|
docker pull nvidia/cuda:10.2-cudnn7-runtime-ubuntu16.04
|
|
|
|
|
# Tensorflow 1
|
|
|
|
|
docker pull tensorflow/tensorflow:1.11.0-py3
|
|
|
|
|
docker pull jupyter/tensorflow-notebook:17aba6048f44
|
|
|
|
|
```
|
2021-12-13 19:13:12 +08:00
|
|
|
|
|
|
|
|
|
Wechat 镜像和启动方法:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
docker pull bestwu/wechat
|
|
|
|
|
xhost +
|
|
|
|
|
docker run -d --name wechat --device /dev/snd --ipc=host \
|
|
|
|
|
-v /tmp/.X11-unix:/tmp/.X11-unix \
|
|
|
|
|
-v $HOME/WeChatFiles:/WeChatFiles \
|
|
|
|
|
-e DISPLAY=unix$DISPLAY \
|
|
|
|
|
-e XMODIFIERS=@im=fcitx \
|
|
|
|
|
-e QT_IM_MODULE=fcitx \
|
|
|
|
|
-e GTK_IM_MODULE=fcitx \
|
|
|
|
|
-e AUDIO_GID=`getent group audio | cut -d: -f3` \
|
|
|
|
|
-e GID=`id -g` \
|
|
|
|
|
-e UID=`id -u` \
|
|
|
|
|
bestwu/wechat
|
|
|
|
|
```
|