docker使用
2020-04-11 18:53:03 # other

Ubuntu 安装Docker

卸载旧版本

1
sudo apt-get remove docker docker-engine docker.io containerd runc

更新包索引

1
sudo apt-get update

安装apt依赖包

1
2
3
4
5
6
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common

添加Docker官方GPG密钥

1
curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -

验证是否带有指纹的密钥

1
sudo apt-key fingerprint 0EBFCD88

设置稳定版仓库

1
2
3
4
sudo add-apt-repository \
"deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/ \
$(lsb_release -cs) \
stable"

更新包索引

1
sudo apt-get update

安装 Docker Engine-Community

1
sudo apt-get remove docker docker-engine docker.io containerd runc

Docker安装Ubuntu

访问 Ubuntu 镜像库地址: https://hub.docker.com/_/ubuntu?tab=tags&page=1

拉取ubuntu镜像

1
2
3
4
5
docker pull ubuntu
# 或者
docker pull ubuntu:latest
# 或者
docker pull ubuntu:对应版本号

测试是否安装成功

1
sudo docker run hello-world

查看本地镜像

1
docker images

运行容器,并且可以通过exec命令进入ubuntu容器

1
docker run -itd --name ubuntu-test ubuntu

查看容器运行信息

1
docker ps

Docker 运行应用程序

1
docker run ubuntu:18.04 /bin/echo "Hello world"
  • docker: Docker的二进制可执行文件。
  • run: 与前面的docker组合起来运行一个容器。
  • ubuntu:18.04: 指定要运行的镜像,如果本地不存在会从镜像仓库Docker Hub下载公共镜像。
  • /bin/echo: “Hello world”: 在容器里执行命令。

运行交互式容器

1
docker run  -i -t ubuntu:18.04 /bin/bash
  • -t: 在容器内指定一个伪终端或终端。
  • -i: 允许你对容器内的标准输入进行交互。

在docker镜像终端进行操作

1
2
cat /proc/version
ls

可以通过exit或者ctrl+D来退出容器

1
exit

启动容器(后台模式)

1
2
3
4
# 使用以下命令创建一个以进程方式运行的容器
docker run -d ubuntu:18.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
# 查看容器是否在运行
docker ps
  • CONTAINER ID: 容器ID
  • IMAGE: 使用的镜像
  • COMMAND: 启动容器时运行的命令
  • CREATED: 容器创建时间
  • STATUS: 容器状态
  1. created(已创建)
  2. restarting(重启中)
  3. running 或 Up(运行中)
  4. removing(迁移中)
  5. paused(暂停)
  6. exited(停止)
  7. dead(死亡)
  • PORTS: 容器的端口信息和使用的连接类型(tcp/udp)。
  • NAMES:自动分配的容器名称。

查看容器的标准输出

1
docker logs # 容器的ID或名字

停止容器

1
docker stop # 容器ID或名字

容器的使用

Docker 客户端

1
2
3
4
# 查看Docker客户端的所有命令选项
docker
# docker command --help 更深入的了解指定命令的使用方法
docker stats --help

运行交互式容器

1
docker run  -i -t ubuntu:18.04 /bin/bash

启动容器

  • -t: 在容器内指定一个伪终端或终端。
  • -i: 允许你对容器内的标准输入进行交互。
  • ubunt:18.04: 镜像
  • /bin/bash: 放在镜像后的是命令,我们希望有个交互式shell,因此用/bin/bash

启动已经停止运行的容器

1
2
3
4
# 查看所有容器的命令
docker ps -a
# 启动一个已经停止的容器
docker start # 容器ID

后台运行

1
2
3
# -d指定容器的运行模式
docker run -itd --name ubuntu-test ubuntu:18.04 /bin/bash
# 加了-d参数默认是不会进入容器,想要进入容器使用指令docker exec

停止容器

1
docker stop # 容器ID

重启容器

1
docker restart # 容器ID

进入容器

1
2
3
4
# 在使用-d参数时,容器启动后会进入后台,此时想进入容器,可以通过以下指令进入:
docker attach # 容器ID
docker exec # 容器ID 此命令退出容器终端,不会导致容器停止。
docker exec -it 2b4bb984ee03 /bin/bash

导出和导入容器
导出容器

1
2
# 导出容器2b4bb984ee03快照到本地文件xx.tar
docker export 2b4bb984ee03 > xx.tar

导入镜像

1
2
3
4
5
6
# 使用docker import从容器快照文件中再导入为镜像
cat 1.tar | docker import - test/ubuntu:v1
# 或者从指定URL或某个目录来导入
docker import http://example.com/exampleimage.tgz example/imagerepo
# 查看导入的镜像
docker images

删除容器

1
docker rm -f # 容器ID

运行一个WEB应用

载入一个WEB镜像

1
2
3
docker pull training/webapp
# 运行
docker run -d -P training/webapp python app.py
  • -d: 让容器在后台运行
  • -P: 将容器内部使用的网络端口随机映射到我们使用的主机上

查看容器

1
2
3
4
5
docker ps
# 此时多了一个PORTS端口信息
0.0.0.0:49153->5000/tcp
# Docker 开放了5000端口(默认Python Flask端口)映射到主机端口49153上。
# 此时我们可以通过浏览器访问WEB应用了 http://ip:49153

通过-p设置端口

1
2
# 容器内部5000端口映射到我们本地主机的5000端口上
docker run -d -p 5000:5000 training/webapp python app.py

查看网络端口的快捷方式

1
docker port 6cb088f8b49a # 端口号或名字

查看WEB应用程序日志

1
docker logs -f 6cb088f8b49a
  • -f: 像tail -f 一样来输出容器内部标准输出

查看WEB应用程序容器的进程

1
docker top 0db42fbc4a2e # 容器ID或名字

检查WEB应用程序

1
2
docker inspect 0db42fbc4a2e
# 使用docker inspect来查看Docker底层信息,他会返回一个JSON文件记录着Docker容器的配置和状态信息。

移除WEB应用容器

1
docker rm 6cb088f8b49a # 删除的容器必须是停止状态,否则将会报错 可以加-f强制删除

Docker镜像的使用

列出镜像列表

1
docker images
  • REPOSITORY: 表示镜像的仓库源
  • TAG: 镜像的标签
  • IMAGE ID: 镜像ID
  • CREATED: 镜像创建时间
  • SIZE: 镜像大小

    同一个仓库源可以有多个TAG,代表这个仓库的不同版本,如ubuntu仓库源里,有18.04、20.04等多个不同的版本,我们使用REPOSITORY:TAG来定义不同的镜像。

查找镜像

1
docker search httpd
  • NAME: 镜像仓库源的名称
  • DESCRIPTION: 镜像的描述
  • OFFICIAL: 是否是docker官方发布
  • STARS: 类型github里面的start,表示点赞、喜欢的意思
  • AUTOMATED: 自动构建

删除镜像

1
docker rmi # 镜像ID

创建镜像
当我们从docker镜像仓库中下载的镜像不能满足我们需求时,我们可以通过以下两种方式对镜像进行更改。

  1. 从已经创建的容器中更新镜像,并提交这个镜像
  2. 使用Dockerfile指令来创建一个新的镜像

更新镜像

1
2
3
4
5
docker commit -m="has update" -a="j" 543307860cfa ubuntu:v1
# 查看我们构建的新镜像ubuntu:v1
docker images
# 运行我们构建的新镜像
docker run -it ubuntu:v1 /bin/bash
  • -m: 提交的描述信息
  • -a: 指定的镜像作者
  • 543307860cfa: 容器ID
  • ubuntu:v1: 要创建的镜像名

构建镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 我们需要创建一个Dockerfile文件,告诉Docker如何构建创建我们的镜像。
vim Dockerfile

FROM ubuntu:18.04
MAINTAINER Fisher "admin@jiangpenghui.cn"
RUN /bin/echo 'root:123456'|chpasswd
RUN useradd "jph"
RUN /bin/echo 'jph:123456'|chpasswd
RUN /bin/echo -r "LANG=\"en_US.UTF-8\"">/etc/default/local
EXPOSE 22
EXPOSE 80
CMD /usr/sbin/sshd -D

:wq

docker build -t ubuntu:v2 .e
  • -t: 指定要创建的目标镜像名。
  • .: Dockerfile文件所在目录。
1
2
3
4
5
6
7
# 查看新创建的镜像
docker images
# 使用新镜像创建容器
docker run -it ubuntu:v2 /bin/bash
# 查看我们创建的用户
id jph
uid=1000(jph) gid=1000(jph) groups=1000(jph)

设置镜像标签

1
2
docker tag 25aebb4abc24 ubuntu:dev
# 此时 25aebb4abc24镜像 多了一个标签

Docker 容器的连接

网络端口映射

1
2
docker run -d -P training/webapp python app.py
docker run -d -p 5000:5000 training/webapp python app.py
  • -P: 是容器内部端口随机映射。
  • -p: 是容器内部端口绑定到指定的主机端口。

我们可以指定容器绑定网络地址,比如绑定127.0.0.1

1
docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py

默认绑定的是tcp端口,如果要绑定udp端口可以在端口后面加上/udp

1
docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py

docker port命令让我们快捷查看端口绑定情况

1
docker port d3373348a178 # 容器id或名字

Docker 容器互联
容器命名

1
2
3
4
docker run -d --name abc -p 127.0.0.1:5000:6000/udp training/webapp python app.py

# 查看容器名称
docker ps -l

新建网络

1
docker network create -d bridge test-net
  • -d: 指定Docker网络类型,有bridge、overlay。

连接容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 运行一个容器并连接到新建的test-net网络
docker run -itd --name test1 --network test-net ubuntu:18.04 /bin/bash
# 打开新终端,在运行一个容器并加入test-net网络
docker run -itd --name test2 --network test-net ubuntu:18.04 /bin/bash

# 安装ping命令
apt-get update
apt install iputils-ping

# 在test1输入以下命令
docker exec -it test1 /bin/bash
ping test2

# 在test2输入以下命令
docker exec -it test2 /bin/bash
ping test1

# test1容器与test2容器建立了互联关系

配置DNS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 在宿主机的/etc/docker/daemon.json文件中增加内容设置全部容器的DNS
{
"dns" : [
"114.114.114.114",
"8.8.8.8"
]
}
# 设置后,启动容器的DNS会自动配置为114.114.114.114和8.8.8.8
#配置完需要重启docker才能生效

# 查看容器DNS是否生效可以使用以下命令,他会输出容器的DNS信息:
docker run -it --rm ubuntu:18.04 cat etc/resolv.conf

# 指定容器设置DNS
docker run -it --rm -h host_ubuntu --dns=114.114.114.114 --dns-search=test.com ubuntu:18.04
  • -rm: 容器退出自动清理容器内部的文件系统。
  • h: HOSTNAME或者-hostname=HOSTNAME: 设定容器的主机名,它会被写到容器内的/etc/hostname和/etc/hosts
  • dns=IP_ADDRESS:添加DNS服务器到容器的/etc/resolv.conf中,让容器用这个服务器来解析所有不再/etc/hosts中的主机名。
  • dns-search=DOMAIN: 设定容器的搜索域,当搜索域设置为.example.com时,在搜索一个名为host的主机时,DNS不仅搜索host,还会搜索host.example.com

Docker仓库管理

注册在 https://hub.docker.com 免费注册一个Docker账号

登录与退出

1
2
docker login
docker logout

推送镜像

1
2
3
4
5
6
# 创建一个镜像
# 命令中的username 替换为你的Docker账户名
docker tag ubuntu:18.04 username/ubuntu:18.04
# 用户登录后可以通过docker push命令将自己的镜像推送到DockerHub
docker push username/ubuntu:18.04
docker search ubuntu

Docker Dockerfile

FROM 和 RUN指令的作用

  • FROM: 定制镜像都是基于FROM的镜像,这里的nginx就是定制需要的基础镜像,后续操作都是基于nginx。
  • RUN: 用于执行后面跟着的命令行命令。有两种格式
  1. RUN <命令行命令> 等同于,在终端操作的shell命令
  2. exec格式 RUN[“可执行文件”, “参数1”, “参数2]
  3. RUN[“./test.php”, “dev”, “offline”] 等价于./test.php dev offline

Dockerfile 的指令没执行一次都会在docker上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如:

1
2
3
4
5
6
7
8
9
10
11
FROM ubuntu
RUN apt install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz

# 以上执行会创建3层镜像。可简化为以下格式:
FROM ubuntu
RUN apt install wget\
&& RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"\
&& RUN tar -xvf redis.tar.gz
# 使用&&符号连接命令,这样执行后,指挥创建1层镜像。

开始构建镜像

1
docker build -t nginx:v1 .

上下文路径
是指在docker构建镜像,有时想用到本机文件,比如赋值,docker build命令得知这个路径后,会将路径下的内容打包。
有序docker运行模式时C/S。我们本机是C,docker引擎是S。实际的构建过程在docker引擎下完成的。所以这个时候无法用到我们本机的文件。这就需要把我们本机的(指定目录下)文件一起打包提供给docker引擎使用。如果未说明最后一个参数,那么默认上下文路径就是Dockerfile所在的位置。
注意: 上下文路径不要放无用的文件,因为会一起打包给docker引擎,如果文件过多会造成过程缓慢。