Docker 安装与使用

Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。

Docker 官网:https://www.docker.com

Github Docker 源码:https://github.com/docker/docker-ce

安装

CentOS 7

yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum makecache
yum -y install docker-ce docker-ce-cli containerd.io
sudo systemctl restart docker
docker run hello-world

CentOS 8

dnf install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
dnf makecache
dnf -y install docker-ce docker-ce-cli containerd.io
sudo systemctl restart docker
docker run hello-world

通过官方自动安装脚本

curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
sudo systemctl restart docker
docker run hello-world

常见安装错误

- problem with installed package podman

sudo dnf remove -y podman # 卸载podma

- problem with installed package buildah

yum install --allowerasing docker-ce

<br/>

配置镜像源

获取镜像地址

<br/>

配置镜像

mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["xxxxxxxxxxx"]
}
EOF
sudo systemctl daemon-reload && sudo systemctl restart docker

注: 请使用镜像地址替换上文xxxxxxxxxxx

Docker的使用

镜像命令

获取镜像

docker pull NAME[:TAG]  
docker pull registry.hub.docker.com/NAME:TAG  # 上面是这条命令的缩写

如果不指定TAG,默认选择latest 标签。镜像文件由很多层组成。下载记录中,每行的开头代表了各层的ID。层是AUFS(Advanced Union File System)中的概念,是实现增量保存与更新的基础。

查看镜像信息

docker images # 列出本机已有的镜像
# REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
#来自于那个仓库   标签信息    镜像的ID号        创建时间       镜像大小
docker tag NAME[:TAG]  NEWNAME[:NEWTAG] # 创建别名
docker inspect <IMAGE ID> # 镜像详细信息
docker inspect -f  {{".Architecture"}} <IMAGE ID> # 删选部分信息

查找镜像

docker search [--automated=false] [--no-trunc=false] [-s, --starts=0]  KEYWORD
#               仅显示自动创建的镜像     输出信息不截断显示    仅显示评价星级以上的

删除镜像

docker rmi [-f] IMAGE [IMAGE...]  

当一个镜像有多个标签,rmi命令只是删除了指定的标签,不影响镜像文件。rmi命令删除镜像时,会先删除所有指向这个镜像的标签,然后才会删除镜像文件本身,注意这个命令必须是 docker rmi <IMAGE ID>,而不是指定名字。当镜像被容器依赖时,不能被删除,除非加了 -f,但是可能造成遗留问题。

创建镜像

基于已有镜像容器创建
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
# OPTIONS 
#    -a, --author=""   作者信息
#    -m, --message=""  提交信息
#    -p, --pause=true  提交时暂停容器运行

流程:

  1. 启动一个镜像
  2. 进行一些修改后退出
  3. 使用commit提交
docker run -ti centos:latest /bin/bash
touch testfile
exit
docker commit <之前的容器ID> # 这条命令会返回新的镜像ID
docker images
基于本地模板导入
  1. 从openvz下载一个模板 下载地址
  2. 使用命令 cat 下载的模板.tar.gz | docker import - <自定义名字>:<TAG>
基于Dockerfile创建

Dockerfile有四部分

  1. 基础镜像信息
  2. 维护者信息
  3. 镜像操作指令
  4. 容器启动时执行指令
FROM ubuntu #指定基于什么的基础镜像,第一条指令必须是FROM指令
FROM <IMAGE> 
FORM <IMAGE>:<TAG>

MAINTAINER m_docker_user docker_user@mail.com #维护者信息
MAINTAINER <NAME> 指定维护者信息

#镜像的操作指令
RUN echo "deb ..."
RUN apt-get update
RUN <COMMAND>
RUN ["EXECUTABLE","PARAM1","PARAM2"]
#每运行一条run指令,镜像添加新的一层,并提交

CMD /bin/mysql #镜像启动时执行的指令,指定的是运行容器时的操作命令
CMD <COMMAND> <PARAM1> <PARAM1>
#CMD只能有一条,多条只有最后一条会被执行
#如果用户指定了启动命令,会覆盖CMD指令

EXPOSE 22 80 443
EXPOSE <PORT> [<PORT>...]
#指定的暴露的端口号,启动时需要用过 -P ,docker会自动分配一个端口转发到指定端口
#使用 -p 可以具体指定那个本地端口映射过来

ENV PATH /usr/local/:$PATH
ENV <KEY> <VALUE>  #指定一个环境变量,会被后续RUN使用,并在容器运行时保持

ADD <SRC> <DEST>
#复制 <SRC> 到容器的 <DEST>。
#src可以是Dockerfile所在目录的一个相对路径,也可以是URL,也可以是tar文件(自动解压为目录)

COPY <SRC> <DEST>
# 和ADD命令一样,ADD支持从远程服务器通过URL获取资源,而且可以读取tar并解压
# COPY更建议用在本地

ENTRYPOINT ["executable","param1","param2"]
ENTRYPOINT command param1 param2 (shell执行)
#配置容器启动后执行的命令,只能有一个,否则执行最后一个。
#CMD指令指定的容器启动时命令可以被docker run指定的命令覆盖
#ENTRYPOINT指令指定的命令不能被覆盖,而是将docker run指定的参数当做ENTRYPOINT指定命令的参数。
#CMD指令可以为ENTRYPOINT指令设置默认参数,而且可以被docker run指定的参数覆盖;

VOLUME ["/data"]
#创建一个可以从本地主机或其他容器挂载的挂载点。

USER daemon
#指定运行容器时的用户名或UID,后续的RUN也会使用指定用户

WORKDIR /path/workdir
#为RUN,CMD,ENTRYPOINY指令配置工作目录
#可以使用多个改命令,后续参数如果为相对路径,则会基于之前命令给予的路径

ONBUILD [INSTRUCTION]
#此镜像作为其他新创建镜像的基础镜像时执行的操作命令。

编写完Dockerfile之后,通过 docker build 创建镜像

使用 .dockerignore文件让Docker忽略路径下的目录和文件

存储和载入镜像

存储镜像
docker save -o xxxx.tar <NAME>:<TAG>
载入镜像
docker load --input xxxx.tar
docker load << xxxx.tar

上传镜像

docker tag test:latest user/test:latest
docker push user/test:latest

容器命令

查看所有容器

docker ps -a

创建容器

新创建的容器默认处于停止状态。

docker create -it <NAME>:<TAG> OR <IMAGE ID>

run命令可以新建一盒容器并启动,或重新启动一个终止状态的容器。

docker run -it <镜像名> /bin/bash 
    #-i: 使容器的标准输入保持打开。-t: 分配一个伪终端。并绑定到容z器的标准输入上 /bin/bash:命令
docker run -itd [--name <随意名字>] <镜像名> /bin/bash #在后台运行
    # -d 守护态运行
    # --rm 容器停止后立即删除,不能与 -d 同用

使用run命令时,docker的操作包括

1.检查本地是否有镜像,没有就下载

2.利用镜像创建容器

3.分配一个文件系统,在只读镜像外挂在一层可读写层

4.从宿主机网桥接口桥接一个虚拟接口到容器

5.从地址池配置一个IP给容器

6.执行用户指定的应用程序

7.执行完毕后容器被终止

启动

docker start <容器 ID>  #启动一个停止的容器,包含文件系统挂载的启动。

停止

docker stop <容器 ID>  [-t|--time[=10]]  #包含文件系统卸载的停止
# 首先会发送SIGTERM信号,等待时间后发送SIGKILL终止容器。

docker kill CONTAINER
# 直接发送SIGKILL来终止容器

重启

docker restart <容器 ID> 
# 重启一个正在运行的容器,不包含文件系统的操作
# 如果容器在运行,会将其终止后重新启动。

进入

docker attach <容器 ID> 
# 如果从这个容器退出,会导致容器停止

docker exec -it <容器 ID> /bin/bash
# exec是直接在容器里运行命令
# 如果从这个容器退出,容器不会停止

PID=$(docker inspect --format "{{.State.Pid}}" <container>) 
nsenter --target $PID --mount --uts --ipc --net --pid
# 类似于docker exec,但是更底层

删除容器

docker rm [-f , --force=false] [-l ,--link=false] [-v --volumes=false] <容器 ID>
#    强制终止并删除一个运行中的容器  删除容器的连接,但保留容器  删除容器挂载的数据卷

导入导出

docker export <容器 ID>   >  file.tar  #导出
cat file.tar | docker import - <镜像名>:[TAG]  #导入成为镜像
# docker import 丢弃所有历史记录和元数据信息,仅保存容器当时的快照状态,比较小,且导入时可重新指定标签等
# docker load 保存完整记录,体积也比较大

网络管理

docker create -it -P <NAME>:<TAG> OR <IMAGE ID>
docker create -it -p 5000:5000 <NAME>:<TAG> OR <IMAGE ID>
docker create -it -p 127.0.0.1:5000:80 <NAME>:<TAG> OR <IMAGE ID>
docker create -it -p 127.0.0.1::5000 <NAME>:<TAG> OR <IMAGE ID>

# 在创建的时候使用  `-P` 命令,将随机映射一个 49000-49900 的端口至容器内部开放的网络端口

# 在创建的时候使用 `-p 本地端口:容器端口 / IP:本地端口:容器端口    / ip::容器端口 ` 映射指定端口
#                映射所有接口地址     / 映射到指定地址的指定端口 /  映射到指定地址的任意端口 

docker port <容器 ID>   # 查看端口映射的配置

概念

  1. 镜像 Image

    ​ 镜像类似于虚拟机镜像,面向docker的只读模板,包含了文件系统

  2. 容器 Container

    ​ 容器类似一个轻量级的沙箱,docker利用它运行隔离应用。容器是从镜像创建的应用实例,容器之间相互隔离。镜像本身是只读的,容器从镜像启动时,docker会在镜像最上层创建一个可写层,镜像保持不变。

  3. 仓库 Repository

    ​ 类似于代码仓库,存放镜像文件的敌方。注册服务器(Registry)是存放仓库的地方。创建仓库后可以通过push命令上传到公有或私有仓库。

私有仓库