一、Docker概述

docker是一种轻量级应用容器引擎,可以将应用与具体操作系统的联系剥离出来,并且可以将不同应用容器相互隔离,能够在保证效率的前提下降低应用之间的相互影响。其设计可以与虚拟机进行类比,但比虚拟机更轻量。由于docker容器具有独立完整的运行环境,可以实现“打包一次,到处运行”(类似上世纪90年代,java的口号“write once, run anywhere”),而且十分轻量,十分适合应用的开发部属,是互联网APP开发的首选。在docker的基础上,还衍生了 Kubernetes(K8S,底层支持不仅是docker)、dockerSwap(docker公司亲儿子)等集群化管理工具,容器化时代已经来临。

1.1 Docker安装

## 安装依赖
yum install -y yum-utils device-mapper-persistent-data lvm2
## 设置仓库
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
## 安装docker
yum install docker-ce docker-ce-cli containerd.io
## 开机启动
systemctl start docker
systemctl enable docker
## 测试安装
docker version
docker run hello-world

## 官方脚本一键安装
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

ubuntu安装参见https://www.runoob.com/docker/ubuntu-docker-install.html

nvidia-docker 安装参见英伟达官网

1.2 基本命令

docker类似于一个独立于操作系统的虚拟机,因此它的操作基本命令都是docker命令的子命令。

1.2.1 pull

docker pull [options] NAME[:TAG]

docker的应用容器建立基础是docker应用镜像。镜像除了可以自己构建外,已经有很多镜像被制作好放到指定仓库中。pull命令的作用在于从远程仓库中下载镜像到docker中。

  • options 一些命令参数选项,通过docker pull —help查看
  • :TAG 用于指定镜像版本,默认是latest。
  • NAME 镜像名称

下例就是获取网易仓库提供的Tomcat镜像。

docker pull hub.c.163.com/library/tomcat:latest

常见docker镜像仓库

1.2.2 images

docker images [options] [REPOSITORY[:TAG]]

获取docker中已安装的镜像,可以列举全部镜像也可以指定镜像名称。

1.2.3 run

docker run [options] IMAGE[:TAG] [COMMAND] [ARG..]

  • IMAGE 镜像名称
  • COMMAND 运行起来的时候要执行什么命令.
  • options 运行参数选项
    • -p 端口映射,将系统端口与docker端口建立映射关系,如 -p 8867:8867
    • -v 文件夹映射,将主机文件与docker文件建立映射关系,如 -v /public/home/zhanghn:/home,前者为主机,后者为容器
    • -d 后台运行,此时不会看到输出日志在控制台
    • —network 用于指定网络,常指定为host,使用主机网络
    • —name 用于指定容器名称,不指定时名称随机,不便于管理

从镜像创建新的容器并运行。

例如创建Ubuntu-vscode的新容器,容器内home文件夹与主机文件夹zhanghn对应,以免相互拷贝文件的麻烦。vscode镜像的base镜像是centos镜像。

docker run -d -p 8867:8067 -v /public/home/zhanghn:/home/zhanghn -v /public/packages:/home/packages --name zhanghn ubuntu-vscode:v3.22.1

docker run -d -p PORT:8067 -v /public/home/USERNAME:/home/USERNAME -v /public/packages:/home/packages —name USERNAME ubuntu-vscode:v3.22.2 —user-data-dir /home/USERNAME/.vscode-server —extensions-dir /home/USERNAME/.local/share/code-server/extensions —config /home/USERNAME/.config/code-server/key.yaml && chmod 666 /home/USERNAME/.config/code-server/key.yaml

容器中可以通过ssh连接外部,但是好像无法直接从外部ssh到容器中。

1.2.3 build

docker build [OPTIONS] PATH | URL |

自定义镜像制作的命令,需要事先撰写Dockerfile,道理类似于CMakeLists.txtMakefiles,为固定文件名。

  • OPTIONS 构建选项,如-t可以为构建镜像命名和版本
  • PATH|URL Dockerfile所在目录或者URL

1.2.4 ps

docker ps

类似于linux命令ps,列举当前运行的或结束的容器进程。

1.2.5 rmi

docker rmi

移除镜像。

1.2.6 rm

docker rm

移除容器。常用组合命令产生已经退出的容器

docker rm `docker ps -a|grep Exited|awk '{print $1}'`

1.2.7 kill

docker kill ID

类似于linux的kill,终止一个容器进程。

1.2.8 start

docker start ID/NAME

不同于run,start用于启动已经创建的容器。

1.2.9 rename

docker rename OLD NEW

对容器进行重命名。

1.2.10 system

docker system prune --volumes -a

清除没用的,悬空的镜像

1.2.11 exec

docker exec -it VSCODE-zhanghn bash

exec命令用于已创建的容器,执行特定的命令,-it选项使得其以终端形式运行。exec命令不受dockerfile的ENTRYPOINT影响。方便以终端形式使用容器。

1.2.12 container

docker container <cmd>

这是docker容器的系列操作命令集

  1. docker container inspect <CONTAINER ID> 查看docker容器配置信息
  2. docker container update <CONTAINER ID> <OPTION> 追加或更新docker容器配置参数,但不是全部都可以

    docker container update VSCODE-zhanghn --restart=always就能修改restart参数

1.2.13 save

docker save -o <*.tar> <Image>

该命令能够将docker镜像保存,便于docker镜像迁移而不必发布到dockerhub上。与docker load对应。

1.2.14 load

docker load -i <*.tar>

将save保存的镜像导入,一般用于镜像迁移。

1.2.15 tag

docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]

该命令给已有的本地镜像打新标签。常见场景是给latest标签的镜像同时起一个别的版本标签方便版本控制。

1.2.16 push

docker push docker push [OPTIONS] NAME[:TAG]

该命令用于将本地镜像发布到镜像仓库,例如默认的dockerhub。

二、Dockerfile

2.1 常见指令

FROM

这是所有非基础镜像都有的指令,而且必须在首行。代表对应的base镜像。可以类比类的集成。

COPY

这是将主机文件拷贝至容器内的指令

ADD

与COPY类似,推荐用COPY。对于tar.gz这种,会将其解压。

ENV

设置容器内环境变量

RUN

在执行docker build时使用,执行相应的bash命令

ENTRYPOINT

在运行容器时使用,类似于C++的main函数,会执行bash命令。注意的是,指令启动的进程是docker容器的1号进程,类似于Linux的1号进程,必须是持续运行的进程。该进程的终结意味着docker容器的终结。可以使用&&进行多条语句,但最后一句必须是持续运行的进程。

CMD

在运行容器时使用,与ENTRYPOINT类似。会被ENTRYPOINT覆盖。可以再build时从命令行接收参数并将内容传给ENTRYPOINT作为参数。因此可以用CMD写不定参。

WORKDIR

设定build时当前工作目录,指的是镜像内目录而非主机目录

三、注意

  1. docker容器启动时以非交互形式进入的bash,因此环境变量等配置只能在~/.bashrc中。

  2. docker容器创建后,可以在相应目录下修改配置参数https://blog.csdn.net/wesleyflagon/article/details/78961990

  3. docker容器默认存储目录修改可以在/etc/docker/daemon.conf中配置graph参数,也可以在/lib/systemd/system/docker.service中配置

    无法使用远程挂载目录作为docker目录,会报错。
    ExecStart=/usr/bin/dockerd —graph=/home/docker

四、docker容器参数修改

这里针对的是已经启动的容器,对于新建容器,只需要在run时增加参数即可。一般性操作在于关闭docker服务,并在对应的docker容器目录下·<dockerRootDir>/containers/<ID>/修改hostconfig.jsonconfig.v2.json。并重启docker。两个配置文件一个针对的是宿主机(host),一个针对的容器自己,配置时需要同步信息。

4.1 追加TCP端口映射

修改hostconfig.json,增加TCP端口绑定。其中key值为docker容器内端口,HostPort为宿主机端口。

“PortBindings”:{
“8067/tcp”:[{“HostIp”:””,”HostPort”:”8067”}],
“8080/tcp”:[{“HostIp”:””,”HostPort”:”28080”}]
}

修改config.v2.json,增加docker端口暴露和端口映射(必须和hostconfig.json对应)。

“ExposedPorts”:{
“8067/tcp”:{},
“8080/tcp”:{}
}

“Ports”:{
“8067/tcp”:[{“HostIp”:”0.0.0.0”,”HostPort”:”8067”}],
“8080/tcp”:[{“HostIp”:”0.0.0.0”,”HostPort”:”28080”}]
}

4.2 追加privilege权限

在创建新docker容器时,--privileged=true可以授予容器与宿主机root用户一样的权限,方便更改一些系统级变量。虽然docker内root是root用户,但对于宿主机来说,它未获得privilege权限时仍然是普通用户,无法修改一些基于宿主机的系统参数。因此privilege权限实际上是宿主机对容器的授权,其配置是针对宿主机的,因此只需要修改hostconfig.json

“Privileged”:true

“SecurityOpt”:[“label=disable”]

“MaskedPaths”:null

“ReadonlyPaths”:null //必须将这些只读路径删除

此时重启后,可以再容器中修改配置sysctl.conf,甚至可以在docker容器中启动docker。

fs.inotify.max_user_watches=524288 //例如在sysctl.conf中设定最大文件监视
sysctl -p

值得注意的是,上述系统变量修改不会持久化保存在docker容器中,重启docker容器需要重新执行sysctl -p

4.3 追加自动重启

在创建新docker容器时,--restart=always可以让容器随着docker服务一起启动,剂自动重启。对于已经有的容器,有两种方法可以实现追加。

  1. update命令

    docker container update <CONTAINER ID> --restart=always

    这个命令前面已经提到过

  2. 修改hostconfig.json中RestartPolicy

    “RestartPolicy”:{“Name”:”no”,”MaximumRetryCount”:0} # 修改前
    “RestartPolicy”:{“Name”:”always”,”MaximumRetryCount”:0} # 修改后

4.4 开放docker远程服务

/lib/systemd/system/docker.service修改如下配置,增加unix和tcp配置。此外可以通过其他配置方法,但多种配置混合会造成冲突而启动失败,故建议统一在dcoker.service中修改。

# for containers run by docker
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2375

而远端可以通过docker -H <ip:port>形式或修改环境变量。2375是默认docker服务端口,可以省略。

docker -H 172.16.10.210 images 所列为远程
export DOCKER_HOST=172.16.10.210:2375
docker images ## 所列为远程服务器docker内容
export DOCKER_HOST=
docker images ## 本地

4.5 修改Docker Root目录

默认情况下,docker的根目录是/var/lib/docker,这里面包含所有镜像和容器等内容。但一般var目录是较小的,不适合生产环境大规模部署。可以通过修改graph参数调整路径,可以有以下两种修改策略。

//查看当前docker root目录
# docker info|grep -i "docker root dir"
Docker Root Dir: /var/lib/docker

//修改/etc/docker/daemon.json,添加"graph":"/docker/docker"
# vim /etc/docker/daemon.json
# systemctl stop docker
# systemctl daemon-reload
# systemctl start docker

//修改/lib/systemd/system/docker.service,在dockerd启动参数中追加 --graph=/docker/docker
# vim /lib/systemd/system/docker.service

五、自建Docker私有仓库

基于register镜像的建立

docker官方提供了一个register镜像,只要拉取并暴露5000端口即建立。

1
2
docker pull register
docker run -d -p 5000:5000 --restart always --name registry registry

然后可以看到http://<host>:5000/v2/_catalog/能被正常访问。此时可以通过设置tag并push到私有仓库
1
2
docker tag <Image>[:tag] <host>:5000/<Target_Imagename>[:tag]
docker push <host>:5000/<Target_Imagename>[:tag]

值得注意的是,如果私有仓库不是localhost,那么需要修改/etc/docker/daemon.json
1
2
3
{
"insecure-registries": ["<host>:5000"]
}

并重启docker服务
1
2
sudo systemctl daemon-reload
sudo systemctl restart docker

国内docker镜像加速器

docker hub和pypi等一样在国内速度慢,可以配置国内镜像源,例如阿里云。
阿里云的镜像需要注册登录获取私有连接,
然后修改/etc/docker/daemon.json

1
2
3
4
5
6
7
8
9
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://****.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

参考文献

  1. github上面超火的code-server+docker安装教程
  2. 新手指南:如何将应用打包成为 Docker 镜像?
  3. Docker容器内不能联网的6种解决方案
  4. CSDN
  5. 知乎-修改 Docker 的默认存储路径
  6. 追加docker容器端口
  7. 修改Docker启动参数
  8. Docker远程
  9. Docker迁移镜像
  10. 自建docker仓库
  11. Docker利用busybox创建基础镜像(base image)