一、简介
从2017年3月开始 docker 在原来的基础上分为两个分支版本:Docker CE 和 Docker EE。
Docker CE 即社区免费版。
Docker EE 即企业版,强调安装但需付费使用。
二、安装 Docker
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
### Ubuntu系统 ### # Docker要求Ubuntu系统的内核版本要高于3.10 ## 脚本获取最新Docker版本安装方法 ## $ sudo wget -qO- https://get.docker.com/ | sh ... ## apt安装 ## $ sudo apt install docker.io ... $ docker ps ...如果遇到权限问题看下文解决 ### CentOS系统 ### # Docker要求CentOS-7为64位系统,内核版本3.10以上 # Docker运行在CentOS-6.5上时候,要求系统为64位,内核版本为2.6.32-432或更高版本 ## yum安装 ## # 移除旧的版本 $ sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-selinux \ docker-engine-selinux \ docker-engine 或用一下命令来删除Docker CE $ sudo yum remove docker-ce $ sudo rm -rf /var/lib/docker # 安装一些必要的系统工具 $ sudo yum install -y yum-utils device-mapper-persistent-data lvm2 ... # 添加阿里云的软件源信息 $ sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo ... # 更新yum缓存 $ sudo yum makecache fast ... # 安装Docker CE社区免费版 $ sudo yum -y install docker-ce ... # 启动Docker后台服务 $ sudo systemctl start docker # 测试是否可以正常调用Docker指令 $ docker ps 或 $ docker yum hello-world ... ### Windows系统 ### 暂时不研究 ### MacOS系统 ### 暂时不研究 |
测试 Docker 能否使用遇到的问题
问题:
1 2 3 |
futuremedia@AgencyServer:~$ docker pull training/webapp Using default tag: latest Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.39/images/create?fromImage=training%2Fwebapp&tag=latest: dial unix /var/run/docker.sock: connect: permission denied |
原因:
由于 Docker 进程使用 Unix Socket 进行通信而不是 TCP 端口,所以,在默认情况下,Unix Socket 是属于 root 用户的,使用时候需要 root 权限才能访问。
解决办法:
- 使用 sudo 获取管理员权限,运行 docker 命令
- Docker 守护线程启动时,会默认赋予名字为 docker 的用户组读写 Unix Socket 的权限,因此只要创建 Docker 用户组(安装 Docker 的时候一般都会自动创建),并将当前用户加入到 docker 用户组中,那么当前用户就有权限访问 Unix Socket 了,进而也就可以执行 Docker 相关命令,具体如下:
123456sudo groupadd docker # 添加docker用户组sudo gpasswd -a $USER docker # 将登陆用户加入到docker或sudo usermod -aG docker $USERnewgrp docker # 更新用户组 断开连接重新连接才会有效docker ps # 测试不使用sudo管理员权限是否可以使用docker命令
三、Docker 容器使用
Docker 客户端
docker 客户端非常简单,可以直接输入 docker 命令来查看 Docker 客户端的所有命令选项 。
还可以用过 docker “command” –help 更深入的了解指定 Docker 命令的使用方法。
运行一个内含 WEB 应用的 Docker 容器
这里直接从网络上拉取 Docker 容器镜像,然后在 docker 容器中通过运行一个 Python Flask 应用来运行一个 web 应用。
1 2 3 4 5 6 7 8 |
futuremedia@AgencyServer:~$ docker pull training/webapp # 载入镜像 futuremedia@AgencyServer:~$ docker run -d -P training/webapp python app.py 或者用-p参数指定端口绑定 futuremedia@AgencyServer:~$ docker run -d -p 5000:5000 training/webapp python app.py 或者加上指定网络地址127.0.0.1绑定 futuremedia@AgencyServer:~$ docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py 或者加上指定网络协议udp绑定(不指定默认为tcp端口) futuremedia@AgencyServer:~$ docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py |
参数说明:
- -d:让容器在后台运行
- -P:将容器内部端口随机映射到主机的高端口
- -p:将容器内部端口绑定到指定的主机端口
查看 WEB 应用容器
可以使用 docker ps 来查看正在运行的容器:
1 2 3 |
futuremedia@AgencyServer:~$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ed6fde093cea training/webapp "python app.py" About an hour ago Up About an hour 0.0.0.0:32768->5000/tcp suspicious_mclaren |
可以看出有一个正在运行的容器,其端口信息:0.0.0.0:32768->5000/tcp
其表示 Docker 开放了 5000 端口(这是默认的 Python Flask 端口)并将之映射到主机的端口 32768 上。
这时候可以通过浏览器访问 WEB 应用了:
1 2 3 4 5 |
(本机浏览器) 0.0.0.0:32768 localhost:32768 (别的机器网络访问,假定这台主机的网络地址为172.31.70.203) 172.31.70.203:32768 |
也可以用过 -p 参数来设置不一样的端口:
1 |
$ docker run -d -p 5000:5000 training/webapp python app.py |
网络端口的快捷方式
通过 docker ps 命令可以查看到容器的端口映射情况,但 docker 还有另一个方法 docker port 查看指定(ID 或者名字)容器。
例如上面创建的容器有:
1 2 |
CONTAINER ID 为 ed6fde093cea NAMES 为 suspicious_mclaren |
则可以使用:
1 2 3 4 5 |
futuremedia@AgencyServer:~$ docker port suspicious_mclaren 5000/tcp -> 0.0.0.0:32768 或者 futuremedia@AgencyServer:~$ docker port ed6fde093cea 5000/tcp -> 0.0.0.0:32768 |
查看 WEB 应用程序日志
docker logs [ID或者名字] 可以查看容器内部的标准输出。
1 2 3 4 5 6 7 |
futuremedia@AgencyServer:~$ docker logs -f ed6fde093cea * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit) 172.31.70.203 - - [11/Oct/2019 07:14:33] "GET / HTTP/1.1" 200 - 172.31.70.203 - - [11/Oct/2019 07:14:33] "GET /favicon.ico HTTP/1.1" 404 - 172.31.70.203 - - [11/Oct/2019 07:14:33] "GET /favicon.ico HTTP/1.1" 404 - 172.17.0.1 - - [11/Oct/2019 07:14:59] "GET / HTTP/1.1" 200 - 172.17.0.1 - - [11/Oct/2019 07:14:59] "GET /favicon.ico HTTP/1.1" 404 - |
-f 让 docker logs 像使用 tail -f 一样来输出容器内部的标准输出。
查看 WEB 应用程序的进程
还可以用 docker top [名字] 来查看容器内部运行进程。
1 2 3 |
futuremedia@AgencyServer:~$ docker top suspicious_mclaren UID PID PPID C STIME TTY TIME CMD root 11881 11860 0 15:11 ? 00:00:00 python app.py |
检查 WEB 应用程序
使用 docker inspect 来查看 Docker 的底层信息。它会返回一个 JSON 文件记录着 Docker 容器的配置&状态信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
futuremedia@AgencyServer:~$ docker inspect suspicious_mclaren [ { "Id": "ed6fde093ceafe349f6820a9c902f0edb118ca7a4da2076b6471da94f90b6979", "Created": "2019-10-11T07:11:16.018299265Z", "Path": "python", "Args": [ "app.py" ], "State": { "Status": "running", "Running": true, "Paused": false, "Restarting": false, "OOMKilled": false, "Dead": false, "Pid": 11881, "ExitCode": 0, "Error": "", "StartedAt": "2019-10-11T07:11:18.628901196Z", "FinishedAt": "0001-01-01T00:00:00Z" }, ...... |
停止 WEB 应用容器
1 2 |
futuremedia@AgencyServer:~$ docker stop suspicious_mclaren suspicious_mclaren |
重启 WEB 应用容器
已经停止的容器,可以使用命令 docker start 来启动。
1 2 3 4 5 6 7 |
futuremedia@AgencyServer:~$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES futuremedia@AgencyServer:~$ docker start suspicious_mclaren suspicious_mclaren futuremedia@AgencyServer:~$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ed6fde093cea training/webapp "python app.py" About an hour ago Up 15 seconds 0.0.0.0:32769->5000/tcp suspicious_mclaren |
正在运行的容器,可以使用 docker restart 命令来重启。
移除 WEB 应用容器
可以使用 docker rm 命令来删除不需要的容器。
1 2 |
futuremedia@AgencyServer:~$ docker rm suspicious_mclaren suspicious_mclaren |
删除容器时,容器必须是停止状态,否则会报错误:
1 2 3 4 |
futuremedia@AgencyServer:~$ docker rm suspicious_mclaren Error response from daemon: You cannot remove a running container ed6fde093ceafe349f6820a9c902f0edb118ca7a4da2076b6471da94f90b6979. Stop the container before attempting removal or force remove |
四、Docker 镜像使用
当运行容器时,使用的镜像如果在本地中不存在,docker 就会自动的从docker镜像仓库中下载,默认是从 Docker Hub 公共镜像源下载。
列出镜像列表
可以使用 docker images 来列出本地主机上的镜像。
1 2 3 4 |
futuremedia@AgencyServer:~$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest fce289e99eb9 9 months ago 1.84kB training/webapp latest 6fae60ef3446 4 years ago 349MB |
参数说明:
- REPOSITORY:表示镜像的仓库源
- TAG:镜像的标签
- IMAGE ID:镜像ID
- CREATED:镜像创建时间
- SIZE:镜像大小
同一个仓库源可以有多个 TAG,代表这个仓库源的不同个版本,例如 ubuntu 仓库源里,有 15.10、14.04 等多个不同的版本骂我们使用 REPOSITORY:TAG 来定义不同的镜像。
所以,如果要使用版本为 15.10 的 ubuntu 系统镜像来运行容器时:
1 2 |
futuremedia@AgencyServer:~$ docker run -t -i ubuntu:15.10 /bin/bash root@77ccb2e5cca:/# |
如果不指定一个镜像的版本标签,那么 docker 会默认使用 ubuntu:latest 镜像。
获取一个新的镜像
当在本地主机上使用一个不存在的镜像时,Docker 会自动下载这个镜像。如果想预先下载这个镜像,可以使用 docker pull 命令来下载它。
1 2 3 4 5 6 7 8 9 |
futuremedia@AgencyServer:~$ docker pull ubuntu:13.10 13.10: Pulling from library/ubuntu 6599cadaf950: Pull complete 23eda618d451: Pull complete f0be3084efe9: Pull complete 52de432f084b: Pull complete a3ed95caeb02: Pull complete Digest: sha256:15b79a6654811c8d992ebacdfbd5152fcf3d165e374e264076aa435214a947a3 Status: Downloaded newer image for ubuntu:13.10 |
下载完成后,可以直接使用这个镜像来运行容器。
查找镜像
在下载镜像前,可以先在 Docker Hub 网站中搜索镜像,Docker Hub 的网址为:https://hub.docker.com/
也可以使用 docker search 命令来搜索镜像。比如需要一个 httpd 镜像来作为 web 服务。可以通过 docker search 命令搜索 httpd 来寻找适合的镜像。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
futuremedia@AgencyServer:~$ docker search httpd NAME DESCRIPTION STARS OFFICIAL AUTOMATED httpd The Apache HTTP Server Project 2692 [OK] centos/httpd 25 [OK] centos/httpd-24-centos7 Platform for running Apache httpd 2.4 or bui… 24 arm32v7/httpd The Apache HTTP Server Project 9 armhf/httpd The Apache HTTP Server Project 8 arm64v8/httpd The Apache HTTP Server Project 4 salim1983hoop/httpd24 Dockerfile running apache config 2 [OK] lead4good/httpd-fpm httpd server which connects via fcgi proxy h… 1 [OK] trollin/httpd 0 dockerpinata/httpd 0 manasip/httpd 0 interlutions/httpd httpd docker image with debian-based config … 0 [OK] itsziget/httpd24 Extended HTTPD Docker image based on the off… 0 [OK] appertly/httpd Customized Apache HTTPD that uses a PHP-FPM … 0 [OK] amd64/httpd The Apache HTTP Server Project 0 izdock/httpd Production ready Apache HTTPD Web Server + m… 0 solsson/httpd-openidc mod_auth_openidc on official httpd image, ve… 0 [OK] buzzardev/httpd Based on the official httpd image 0 [OK] manageiq/httpd_configmap_generator Httpd Configmap Generator 0 [OK] ppc64le/httpd The Apache HTTP Server Project 0 tugboatqa/httpd The Apache HTTP Server Project 0 publici/httpd httpd:latest 0 [OK] manageiq/httpd Container with httpd, built on CentOS for Ma… 0 [OK] waja/httpdiff Docker image for httpdiff: https://github.co… 0 [OK] alvistack/httpd Docker Image Packaging for Apache 0 [OK] |
参数说明:
- NAME:镜像仓库源名字
- DESCRIPTION:镜像的描述
- OFFICIAL:是否 docker 官方发布
拖取镜像
(这里用 httpd 来作例子)
拖取就用上面介绍的命令 docker pull httpd 来下载镜像即可。
下载完成后,就可以用 docker run httpd 在本地 docker 库中直接运行了。
创建镜像
当从 docker 镜像仓库中下载的镜像不能满足需求时,可以通过以下两种方式对镜像进行更改。
- 从已经创建的容器中更新镜像,并且提交这个镜像
- 使用 Dockerfile 指令来创建一个新的镜像
更新镜像
更新镜像之前,需要使用镜像来创建一个容器。
1 2 |
futuremedia@AgencyServer:~$ docker run -t -i ubuntu:16.04 /bin/bash root@e218edb10161:/# |
在运行的容器内使用 apt-get upgrade 命令进行更新。
在完成操作之后,输入 exit 命令来退出这个容器。
此时 ID 为 e218edb10161 的容器,就是 upgrade 过后,经过更改的容器。然后通过命令 docker commit 来提交容器副本。
1 2 |
futuremedia@AgencyServer:~$ docker commit -m="has update" -a="futuremedia" e218edb10161 futuremedia/ubuntu:v2 sha256:70bf1840fd7c0d2d8ef0a42a817eb29f854c1af8f7c59fc03ac7bdee9545aff8 |
参数说明:
- -m:提交的描述信息
- -a:指定镜像作者
- e218edb10161:容器ID
- futuremedia/ubuntu:v2:指定要创建的目标镜像名
再然后可以使用 docker images 命令来查看到新的镜像 futuremedia/ubuntu:v2:
1 2 3 4 5 |
futuremedia@AgencyServer:~$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE futuremedia/ubuntu v2 e218edb10161 15 seconds ago 158.5 MB hello-world latest fce289e99eb9 9 months ago 1.84kB training/webapp latest 6fae60ef3446 4 years ago 349MB |
重新使用这个新镜像 futuremedia/ubuntu 来启动一个容器。
1 2 |
futuremedia@AgencyServer:~$ docker run -t -i futuremedia/ubuntu:v2 /bin/bash root@e218edb10161:/# |
构建新镜像
使用命令 docker build,从零开始来创建一个新的镜像。为此,需要创建一个 Dockerfile 文件,其中包含一组指令来告诉 Docker 如何构建这个镜像。
1 2 3 4 5 6 7 8 9 10 11 |
futuremedia@AgencyServer:~$ cat Dockerfile FROM centos:6.7 MAINTAINER EngineerC "szu_ch@szu.edu.cn" RUN /bin/echo 'root:123456' |chpasswd RUN useradd futuremedia RUN /bin/echo 'futuremedia:123456' |chpasswd RUN /bin/echo -e "LANG=\"en_US.UTF-8\"" >/etc/default/local EXPOSE 22 EXPOSE 80 CMD /usr/sbin/sshd -D |
这个查看一个名字为 Dockerfile 的文件信息。其中,每一个指令都会在镜像上创建一个新的层,每一个指令的前缀都必须是大写的。
第一条 FROM,指定使用哪个镜像源
RUN 指令告诉 docker 在镜像内执行命令,安装了什么。
然后,使用 Dockerfile 文件,通过 docker build 命令来构建一个镜像。
1 |
futuremedia@AgencyServer:~$ docker build -t futuremedia/centos:6.7 . |
参数说明:
- -t:指定要创建的目标镜像名
- .:Dockerfile 文件所在目录,可以指定 Dockerfile 的绝对路径
使用 docker images 查看创建的镜像已经在列表中存在,镜像 ID 为 860c279d2fec
1 2 3 4 5 6 |
futuremedia@AgencyServer:~$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE futuremedia/centos 6.7 860c279d2fec About a minute age 190.6 MB futuremedia/ubuntu v2 e218edb10161 15 seconds ago 158.5 MB hello-world latest fce289e99eb9 9 months ago 1.84 kB training/webapp latest 6fae60ef3446 4 years ago 349 MB |
可以使用新的镜像来创建容器
1 2 3 |
futuremedia@AgencyServer:~$ docker run -t -i futuremedia/centos:6.7 /bin/bash [root@860c279d2fec /]# id futuremedia uid=500(futuremedia) gid=500(futuremedia) groups=500(futuremedia) |
上面的镜像信息显示有包含创建的用户 futuremedia
设置镜像标签
使用 docker tag 命令,为镜像添加一个新的标签。
1 |
futuremedia@AgencyServer:~$ docker tag 860c279d2fec futuremeida/centos:dev |
docker tag 镜像 ID,这里是 860c279d2fec,用户名称、镜像源名(repository name)和新的标签名(tag)。
五、Docker 实例安装 Python
方法一:docker pull python:3.5
- 使用 docker search python 命令查找 Docker Hub 上的 python 镜像:
1docker search python - 拉取官方镜像标签为 3.5 版本的 python 镜像:
1docker pull python:3.5 - 下载完成后,在本地镜像列表查到标签为 3.5 的 python 镜像:
1docker images python:3.5
方法二:通过 Dockerfile 构建
- 首先,创建目录 python,用于存放后面相关的东西:
1futuremedia@AgencyServer:~$ mkdir -p ~/python ~/python/myapp
myapp目录将映射为 python 容器配置的应用目录。 - 进入创建的 python 目录,创建 Dockerfile 文件:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152### Dockerfile ###FROM buildpack-deps:jessie# remove several traces of debian pythonRUN apt-get purge -y python.*# http://bugs.python.org/issue19846# > At the moment, setting "LANG=C" on a Linux system *fundamentally breaks Python 3*, and that's not OK.ENV LANG C.UTF-8# gpg: key F73C700D: public key "Larry Hastings <larry@hastings.org>" importedENV GPG_KEY 97FC712E4C024BBEA48A61ED3A5CA953F73C700DENV PYTHON_VERSION 3.5.1# if this is called "PIP_VERSION", pip explodes with "ValueError: invalid truth value '<VERSION>'"ENV PYTHON_PIP_VERSION 8.1.2RUN set -ex \&& curl -fSL "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz" -o python.tar.xz \&& curl -fSL "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz.asc" -o python.tar.xz.asc \&& export GNUPGHOME="$(mktemp -d)" \&& gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$GPG_KEY" \&& gpg --batch --verify python.tar.xz.asc python.tar.xz \&& rm -r "$GNUPGHOME" python.tar.xz.asc \&& mkdir -p /usr/src/python \&& tar -xJC /usr/src/python --strip-components=1 -f python.tar.xz \&& rm python.tar.xz \\&& cd /usr/src/python \&& ./configure --enable-shared --enable-unicode=ucs4 \&& make -j$(nproc) \&& make install \&& ldconfig \&& pip3 install --no-cache-dir --upgrade --ignore-installed pip==$PYTHON_PIP_VERSION \&& find /usr/local -depth \\( \\( -type d -a -name test -o -name tests \) \-o \\( -type f -a -name '*.pyc' -o -name '*.pyo' \) \\) -exec rm -rf '{}' + \&& rm -rf /usr/src/python ~/.cache# make some useful symlinks that are expected to existRUN cd /usr/local/bin \&& ln -s easy_install-3.5 easy_install \&& ln -s idle3 idle \&& ln -s pydoc3 pydoc \&& ln -s python3 python \&& ln -s python3-config python-configCMD ["python3"]
通过 Dockerfile 创建一个镜像,替换成自己命名的名字:
1futuremedia@AgencyServer:~/python$ docker build -t python:3.5 .
创建完成后,可以在本地的镜像列表里查到刚刚创建的镜像:
1futuremedia@AgencyServer:~/python$ docker images python:3.5
使用 python 镜像
在 ~/python/myapp 目录下创建一个 helloworld.py 文件,代码如下:
1 2 3 |
#!/usr/bin/python print("Hello, World!") |
运行容器:
1 2 |
futuremedia@AgencyServer:~/python$ docker run -v $PWD/myapp:/usr/src/myapp -w /usr/src/myapp python:3.5 python helloworld.py Hello, World! |
参数说明:
- -v $PWD/myapp:/usr/src/myapp:将主机中当前目录下的 myapp 挂载到容器的 /usr/src/myapp
- -w /usr/src/myapp:指定容器的 /usr/src/myapp 目录为工作目录
- python helloworld.py:使用容器的 python 命令来执行工作目录中的 helloworld.py 文件
EX.1 关于 docker 和 NVIDIA
直接使用 docker 貌似不能调用到 NVIDIA 的显卡,根据页首的图,可以看到是分割的,需要在 Docker 层和 NVIDIA 层之间加入 nvidia-docker 插件,使的 docker 能支持调用 NVIDIA Driver。具体安装如下:
在安装完 Docker-CE 后才能安装 nvidia-docker2,因为这是依赖于 Docker 的。
安装步骤
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# Add Sources $ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) $ curl -s -L https://nvidia-github.io/nvidia-docker/$distribution/nvidia-docker.list | \ > sudo tee /etc/apt/sources.list.d/nvidia-docker.list # Install nvidia-docker2 $ sudo apt-get install nvidia-docker2 # ReStart Docker Daemon $ sudo pkill -SIGHUP dockerd # Test nvidia-docker2 $ sudo nvidia-docker run --rm nvidia/cuda:latest nvidia-smi or $ sudo docker run --runtime nvidia --rm nvidia/cuda:latest nvidia-smi # if have nvidia-smi message that mean it is work |
错误报告
跑测试的时候可能会出现:
【报错】
docker: Error response from daemon: OCI runtime create failed: container_linux.go:345: starting container process caused “process_linux.go:430: container init caused “process_linux.go:413: running prestart hook 1 caused \“error running hook: exit status 1, stdout: , stderr: nvidia-container-cli: requirement error: unsatisfied condition: cuda>=10.1\\n\”””: unknown.
【原因】系统中安装的 CUDA 版本和镜像要求的 CUDA 版本不一致
【解决方法】 下载相应的 CUDA 版本镜像例如:docker run –runtime=nvidia –rm nvidia/cuda:9.0-base nvidia-smi