安装配置
这里仅以CentOS 安装 Docker CE 举例说明。详见Docker 官方 CentOS 安装文档
准备工作
系统要求
Docker CE 支持 64 位版本 CentOS 7,并且要求内核版本不低于 3.10。 CentOS 7 满足最低内核的要求,但由于内核版本比较低,部分功能(如 overlay2
存储层驱动)无法使用,并且部分功能可能不太稳定。
警告:切勿在没有配置 Docker YUM 源的情况下直接使用 yum 命令安装 Docker.
卸载旧版本
旧版本的 Docker 称为 docker
或者 docker-engine
,使用以下命令卸载旧版本:
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine
使用脚本安装(非生产环境)
对于个人测试,可以使用这个脚本自动化安装Docker:
curl -fsSL get.docker.com -o get-docker.sh
sh get-docker.sh
但是,需要注意, 这个脚本可能扰乱你的系统配置、安装及大量的(你可能用不到的)依赖,并且只能安装最新(可能未经充分测试的)版本的Docker , 所以不推荐在生产环境中使用。
使用 yum 安装
安装依赖包:
sudo yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
添加 yum
软件源:
# 中国科学技术大学开源软件镜像源
sudo yum-config-manager \
--add-repo \
https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.repo
# 官方源
# sudo yum-config-manager \
# --add-repo \
# https://download.docker.com/linux/centos/docker-ce.repo
更新 yum
软件源缓存,并安装 docker-ce
。
sudo yum makecache fast
sudo yum install docker-ce
离线安装
以docker-ce-18.03.1为例:
- 在
https://download.docker.com/linux/centos/7/x86_64/stable/Packages/
这里找到对应rpm包 - 执行安装命令:
rpm -ivh docker-ce-18.03.1.ce-1.el7.centos.x86_64.rpm
- 由于安装环境不同,可能会发现缺少一些相关依赖包(eg: libcgroup、libtool-ltdl、container-selinux)前往
https://pkgs.org/
或https://buildlogs.centos.org/
下载对应依赖包,依次安装即可
启动 Docker CE
sudo systemctl enable docker
sudo systemctl start docker
建立 Docker 用户组
默认情况下,docker命令需要root
权限,为了避免每次输入命令都要加sudo
,可以将用户加入 docker
用户组:
sudo groupadd docker
sudo usermod -aG docker $USER
退出当前终端并重新登录,进行如下测试。
测试 Docker 是否安装正确
执行
docker run hello-world
Docker会从官方仓库下载hello-world镜像并启动,如果一切正常的话会看到类似如下提示:
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
ca4f61b1923c: Pull complete
Digest: sha256:be0cd392e45be79ffeffa6b05338b98ebb16c87b255f48e297ec7f98e123905c
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://cloud.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/engine/userguide/
镜像加速
鉴于国内网络问题,建议使用Docker中国或者其他国内镜像源。
修改(或新增)/etc/docker/daemon.json
文件,添加:
{
"registry-mirrors": ["https://registry.docker-cn.com"]
}
之后重启Docker使配置生效。
常用Docker操作
# 查看docker版本
docker version
# 显示docker系统的信息
docker info
# 日志信息
docker logs
# 故障检查
service docker status
# 启动关闭docker
sudo service docker start|stop
使用镜像
基本操作
以redis为例,我们从Docker Hub上获取官方镜像到本地:
docker pull redis
ps1:由于redis是官方源(Official),否则应该写完整的两段式仓库名 <用户名>/<软件名>
,例如bitnami/redis。
ps2:此处没有指定镜像版本,默认会拉取redis:lastest镜像,指定版本应该写成例如:redis:5.0-rc5
查看已经下载的镜像:
docker image ls
# 会有类似如下显示
REPOSITORY TAG IMAGE ID CREATED SIZE
redis latest 5f515359c7f8 5 days ago 183 MB
......
更细节的显示可以使用docker image ls --format "{{.ID}}: {{.Repository}}"
直接列出镜像ID和仓库名,
或者使用docker image ls --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}"
以表格等距显示.
如果要删除某个镜像的话,可以使用docker image rm {IMAGE ID}|{REPOSITORY}
命令,不要过先确保没有容器在使用这个镜像。
Dockerfile
除了引用制作好的镜像,我们也可以基于现有镜像定制新的镜像。定制所用的脚本文件就是 Dockerfile。
Dockerfile 是一个文本文件,其内包含了一条条的 指令(Instruction) ,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
我们新建一个空白文件,命名为 dockerfile
,再文件中写入如下内容:
FROM redis
RUN mkdir redis
WORKDIR redis
COPY ./redis.conf /etc/
CMD ["redis-server", "/etc/redis.conf"]
我们依次解释上面每一行:
- FROM 就是指定 基础镜像 ,一个
Dockerfile
中FROM
是必备的指令,并且必须是第一条指令。如果不以任何镜像为基础,那应该用FROM scratch
作为起始指令。 RUN 是Dockerfile的核心指令,用于执行一条命令,由于Dockerfile 每一条指令都会新建一层,所以应该尽量将执行的内容写在一行(多行内容可以通过在末尾加
\
以表示未结束),它有两种写法:- shell 格式:
RUN <命令>
,就像直接在命令行中输入的命令一样。 - exec 格式:
RUN ["可执行文件", "参数1", "参数2"]
,这更像是函数调用中的格式。
- shell 格式:
- WORKDIR 表示指定当前工作目录,相当于
cd
命令。 - COPY 即复制文件到容器中,在这里是把redis.conf文件复制到容器的
/etc
目录下。 - CMD 是启动程序的命令,写法和
RUN
相同,一般推荐使用exec
格式。
常用Docker指令列表如下:
指令 | 含义 | 用法 | |
---|---|---|---|
FROM | 指定基础镜像 | FROM <基础镜像> |
|
RUN | 执行指令 | RUN ["可执行文件", "参数1", "参数2"] |
|
COPY | 复制文件 | COPY ["<源路径1>",... "<目标路径>"] |
|
ADD | 更高级的复制文件 | ADD "<压缩文件>" |
|
CMD | 容器启动命令 | CMD ["可执行文件", "参数1", "参数2"...] |
|
ENTRYPOINT | 入口点 | ENTRYPOINT ["可执行文件", "参数1", "参数2"] |
|
ENV | 设置环境变量 | ENV <key1>=<value1> <key2>=<value2>... |
|
ARG | 构建参数 | ARG <参数名>[=<默认值>] |
|
VOLUME | 定义匿名卷 | VOLUME ["<路径1>", "<路径2>"...] |
|
EXPOSE | 暴露端口 | EXPOSE <端口1> [<端口2>...] |
|
WORKDIR | 指定工作目录 | WORKDIR <工作目录路径> |
|
USER | 指定当前用户 | USER <用户名> |
|
HEALTHCHECK | 健康检查 | `HEALTHCHECK NONE | [选项] CMD <命令>` |
ONBUILD | 构建下级镜像 | ONBUILD <其它指令> |
|
MAINTAINER | 指定作者 | ONBUILD <作者> |
更多指令及用法请参照官方文档
如上,我们完成了一个使用自己配置文件的redis镜像的准备工作,之后依据这个Dockerfile进行构建:
docker build -t redis_test:v0.1 .
# 会有类似如下输出:
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM redis
...
...
Removing intermediate container 9cdc27646c7b
Successfully built 44aa4490ce2c
docker build
的用法为:
docker build [选项] <上下文路径/URL/->
最后,可以使用docker push
将你自己构建的镜像上传到仓库中,详细用法见官方文档 push
容器操作
容器启停
我们可以用这样的方式从之前的镜像启动一个容器:
docker run -d --name some-redis redis
docker run
的用法为docker run [选项] 镜像 [命令] [参数...]
,其中:
--name
指定容器的名称, -d
指定后台运行,其他常用参数包括-i
交互式操作,-t
使用终端(it
一般同时使用),--rm
容器退出后随之将其删除,完整参数列表可以通过--help
或者在线文档 docker run查看
由于我们是在后台运行,使用docker container ls
来查看容器相关情况,如果要查看停止的进程,后面需要增加参数-a
:
docker container ls
# 会看到类似如下内容
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
77b2dc01fe0f redis:v2 redis-server redis.conf 'while tr 2 minutes ago Up 1 minute agitated_wright
使用docker container stop
来结束容器的运行:
docker container stop 77b2dc01fe0f
类似的,使用docker container start | restart | stop
可以控制容器的启停,
使用docker container rm
来删除指定容器。
数据管理
之前提到过,随着容器的销毁,容器内的数据也会一同丢失。为了保存数据,Docker提供了两种方式(还有一种tmpfs mountsb不常用到):
方式1:数据卷(推荐)
数据卷 volume
是一个可供一个或多个容器使用的特殊目录,它不依赖于Unix文件系统,也拥有独立于容器的生命周期。
创建一个数据卷:
docker volume create my-vol
查看数据卷及具体信息:
# 查看所有的数据卷
docker volume ls
# 会看到类似如下内容
local my-vol
# -----------------------------------
# 查看具体卷的信息
docker volume inspect my-vol
# 会看到类似如下内容
[
{
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
"Name": "my-vol",
"Options": {},
"Scope": "local"
}
]
在用 docker run 的时候,增加 --mount
参数来使用数据卷,还是以启动redis为例,这里我们启动redis并且开启aof持久化:
docker run -d \
--name redis \
--mount source=my-vol,target=/data \
# -v my-vol:/data \
redis \
redis-server --appendonly yes
在这里redis产生的数据(/data
目录下)被挂载到数据卷my-vol
中。
我们也可以使用-v
或者--volume
语法,但是官方建议尽量使用--mount
。
同样使用inspect
语法,我们可以查看redis容器的信息:
docker inspect redis
# 会看到类似如下内容
"Mounts": [
{
"Type": "volume",
"Name": "my-vol",
"Source": "/var/lib/docker/volumes/my-vol/_data",
"Destination": "/data",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
方式2:绑定主机目录
我们也可以直接将容器的数据挂载 bind mount
到宿主机的目录或文件 (而非由Docker创建的数据卷),以当前目录$(pwd)
为例:
docker run -d \
--name redis \
--mount type=bind,source="$(pwd)"/target,target=/data \
redis \
redis-server --appendonly yes
挂载单独文件的方法类似。
需要注意,本地目录必须存在,否则会报错。
区别
Volumes是由Docker创建和管理,存储在宿主机固定位置(在linux上是/var/lib/docker/volumes/)。 非Docker应用程序不能改动这一位置的数据。 一个数据卷可以同时被挂载到几个容器中。即使没有正在运行的容器使用这个数据卷,它依然不会清除。可以通过docker volume prune
清除不再使用的数据卷。
Bind mounts的数据可以存放在宿主机的任何地方。 非Docker应用程序可以改变这些数据。
使用网络
端口映射
docker run
的时候使用-P
(—publish-all)参数,随机映射一个 49000~49900 的端口到内部容器开放的网络端口。
或者使用-p ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort
(—publish)来指定具体端口映射:
docker run -d \
--name some-redis \
-p 6379:6379 \
-p 127.0.0.1::16379/udp
-p 127.0.0.1:80:80
redis
这里我们分别将容器的6379端口映射到宿主机 任意ip的6379端口 ,容器的16379 udp端口映射到宿主机的 任意端口 ,容器的80端口映射到宿主机 对应的80端口 。
使用docker port
可以查看对应容器的全部端口映射。
容器互联
简单的容器互联可以通过--link
实现,但是 官方未来可能会删除这个参数 ,所以不展开。
最新的方式是搭建docker网络实现容器互联,先创建一个新的 Docker 网络:
docker network create -d bridge my-net
这里的-d
参数指定网络类型,常用的只有bridge,其他的可能会在Swarm用到,如果不知道Swarm是什么就不用在意。
以redis客户端/服务端为例,分别在启动的时候将之加入my-net
网络:
docker run -d \
--name redis-server \
--network my-net \
redis
docker run -it \
--rm \
--name redis-client \
--network my-net \
redis redis-cli -h redis-server
可以看到成功进入redis-cli客户端,我们可以尝试info
/keys *
或者其他命令查看redis服务端运行情况。
延申
容器编排
面临一组容器配合使用的情况,例如一个包括负载均衡——网站后台——数据库的Web系统,我们可以使用Docker提供的Compose完成统一配置管理。它将提供相同功能的容器定义为服务service
——以方便复用;将完整的容器组合组成项目project
以方便统一管理。所有的配置通过一个yml文件即可实现。
Nvidia Docker
对使用GPU的容器,Docker提供Nvidia Docker以发挥GPU的运算性能。
基本要求如下:
- GNU/Linux x86_64 with kernel version > 3.10
- Docker >= 1.12
- NVIDIA GPU with Architecture > Fermi (2.1)
- NVIDIA drivers ~= 361.93 (untested on older versions)
详细安装使用见官方项目Wiki)
实例
项目地址: awesome-docker