【Kubernetes】Docker + K8s 实践之路(Docker篇)
认识Docker定义Docker 是一个基于 Go 语言 的 开源的应用容器引擎,基于 Linux 内核的 cgroup,namespace,以及 OverlayFS 类的 Union FS 等技术,对进程进行封装隔离,属于 操作系统层面的虚拟化技术。Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化;容器是完
认识Docker
定义
-
Docker 是一个基于 Go 语言 的 开源的应用容器引擎,基于 Linux 内核的 cgroup,namespace,以及 OverlayFS 类的 Union FS 等技术,对进程进行封装隔离,属于 操作系统层面的虚拟化技术。
-
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化;
-
容器是完全使用沙箱机制,相互之间不会有任何接口。
架构
-
镜像:OS分为内核和用户空间,Linux的用户空间就是root文件系统,Docker镜像就相当于一个root文件系统,利用 Union FS 的技术设计成了多层架构,每一层可被复用,从而减少镜像的拉取,或减小镜像体积。
-
容器:类似于面向对象中类与对象的关系,容器可以理解为镜像的实例, 可以创建、启动、停止、删除、暂停等。容器内的进程运行在一个隔离的环境下;容器如果需要写入操作,应该使用数据卷,如果直接往容器内写数据,容器消失后数据也会消失,数据卷则会持久化存在宿主机器。
-
仓库:Docker Registry是存储镜像仓库的地方,每个镜像仓库可以有多个标签,每个标签对应一个镜像,可以用来标识镜像版本。
Docker Registry 公开服务可以给用户提供公开镜像的下载,也可以将自己做的镜像上传到公开服务的个人用户中,常用的公开服务有 Docker Hub、 网易云镜像服务、DaoCloud 镜像市场、阿里云镜像库等。
我们可以通过docker pull 命令从共有Docker Registry中拉取镜像,拉取前建议先读一下镜像的使用说明,比如版本号,使用demo等,网址为:
https://hub.docker.com/
我们也可以在自己的服务器上搭建私有的Docker Registry,从而在本地管理我们的镜像文件。
优势
- 简化配置
- 代码流水线(Code Pipeline)管理
- 隔离应用
- 整合服务器,使资源更有效利用
- 调试能力
- 快速部署
和 VMware比较的优势
- VMware 是操作系统级别的隔离,操作系统的运行本身也会占内存和硬盘
- 操作系统重启很慢
镜像
镜像相当于一个 ROOT 文件系统;
提供容器运行时所需的程序、库、资源、配置等文件,还包含容器运行时可能需要的一些配置参数(如匿名卷、环境变量、用户等);
镜像不包含任何动态数据,其内容在构建之后也不会被改变;
镜像 利用 Union FS 的技术,设计为分层存储的架构,从而方便镜像层的复用,节约镜像体积。
有很多现成的镜像可以直接通过from调用,并在其之上搭建所需镜像;
还有一个特殊镜像 scratch,表示空白镜像,如果以 scratch 为基础镜像的话,意味着你不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始存在。
对于 Linux 下静态编译的程序来说,并不需要有操作系统提供运行时支持,所需的一切库都已经在可执行文件里了,因此直接 FROM scratch 会让镜像体积更加小巧。
使用 Go 语言 开发的应用很多会使用这种方式来制作镜像,这也是为什么有人认为 Go 是特别适合容器微服务架构的语言的原因之一。
容器
镜像是定义,容器是镜像的实体,也可以理解为 以镜像为基础层,在其上创建一个当前容器的存储层;
存储层和容器一起创建,也会一起消失;
对容器读写应使用数据卷或挂在主机目录;
容器的本质是进程,且有自己独立的命名空间,因此有自己的 ROOT 文件系统、网络配置等,可以把内部的应用程序隔离起来。
Docker Registry
存取镜像的地方,可以是 用户名/软件名 或者 用户名/软件名:版本号,可以用公有的docker hub或国内镜像仓库,也可以自己搭建仓库。
Docker的安装
环境
OS:ubuntu18.04
Docker:19.03.8
卸载机器上的旧版本Docker(如之前没安装可跳过)
1、删除docker组件
sudo apt remove docker docker-ce docker-engine docker.io containerd runc
2、删除残留的 镜像、容器、数据卷、网络、配置等
sudo apt purge docker-ce
sudo rm -rf /var/lib/docker
APT安装(推荐)
1、更新APT软件包索引
sudo apt update
2、添加使用 HTTPS 传输的软件包以及 CA 证书
sudo apt install \
apt-transport-https \
ca-certificates \
curl \
software-properties-common
3、添加软件源的 GPG 密钥
# 阿里源
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
# 官方源
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
4、设置stable repository,向 source.list 中添加 Docker 软件源
sudo apt-get install software-properties-common
# 阿里
sudo add-apt-repository \
"deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu \
$(lsb_release -cs) stable"
# 官方
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
5、查看可安装的Docker版本
apt-cache madison docker-ce
6、安装DOCKER引擎
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io
其他安装方式
1、deb安装
进入 https://download.docker.com/linux/ubuntu/dists/ 选择Ubuntu版本,然后进入pool/stable/,选择amd64, armhf,arm64,ppc64el,或s390x,并下载.deb文件,然后执行如下命令安装
sudo dpkg -i /path/to/package.deb
2、便捷脚本安装
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
验证安装
输入docker version,出现如下信息,则安装成功,同时看到本次安装的Docker版本是19.03.8,API的版本和GO的版本也可以看到,下面一行小字提醒当前权限不够,可以通过下一小节的Docker用户组解决。
docker version
Client: Docker Engine - Community
Version: 19.03.8
API version: 1.40
Go version: go1.12.17
Git commit: afacb8b7f0
Built: Wed Mar 11 01:25:46 2020
OS/Arch: linux/amd64
Experimental: false
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.40/version: dial unix /var/run/docker.sock: connect: permission denied
建立Docker 用户组
默认情况下,docker 命令会使用 Unix socket 与 Docker 引擎通讯。而只有 root 用户和 docker 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 root 用户。因此,更好地做法是将需要使用 docker 的用户加入 docker 用户组;
执行如下命令后重启终端即可生效。
sudo groupadd docker
sudo usermod -aG docker 当前用户
Docker的配置与启动
创建并修改daemon.json文件
这里以配置国内镜像源为例,由于镜像服务可能出现宕机,建议同时配置多个镜像源,这里优先推荐 阿里或者daocloud的镜像源。
阿里镜像地址:https://cr.console.aliyun.com/
cd /etc/docker
sudo touch daemon.json
sudo vim daemon.json
# 加入以下内容
{
"registry-mirrors": ["https://xxxx.mirror.aliyuncs.com"]
}
esc -> :wq -> enter
启动Docker
# 设置为开机自动启动Docker服务
sudo systemctl enable docker
# 启动Docker服务
sudo systemctl start docker
修改后需重载配置并重启Docker服务
sudo systemctl daemon-reload
sudo systemctl restart docker
查看更改是否生效
sudo systemctl status docker -l
sudo docker info
启动一个镜像
docker run hello-world
# 输出显示:
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete
Digest: sha256:8e3114318a995a1ee497790535e7b88365222a21771ae7e53687ad76563e8e76
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.
重置本地 Docker 的所有数据
sudo rm -rf /var/lib/docker
搭建私有仓库
本节利用官方提供的docker-registry工具搭建私有仓库,用来我们存放制作的镜像,用的时候只需要从本地拉取,省时间。
安装docker-registry
1、查看镜像源中的registry镜像
docker search registry
2、拉取镜像
这一步可以省略,可直接执行run命令启动容器,在指定镜像时会自动拉取。
# 该指令会默认拉取镜像源官方的latest标签
docker pull registry
# 查看本地镜像
docker images
3、运行容器
docker run -d -p 5000:5000 --name mda_registry \
-v /usr/mda_registry:/var/lib/registry \
--restart=always registry:latest
# 查看启动的容器
docker ps
# 查看容器mda_registry的IP地址(172.17.0.2)
docker inspect mda_registry| grep IPAddress
-d:后台运行容器
-p:将主机端口映射到容器端口
–name:容器名称
-v 将主机目录映射到容器内目录
–restart:容器重启机制
registry:latest:使用的镜像及镜像标签
4、查看私有仓库的镜像
curl http://172.17.0.2:5000/v2/_catalog
5、上传一个镜像(以python镜像为例)
从Docker Hub拉取一个python3.8版本的镜像,建议拉取前登录docker hub查看镜像标签及使用样例,https://hub.docker.com/_/python?tab=tags
# 从Docker Hub拉取一个镜像
docker pull python:3.8
# 查看
docker images
打标签,标签的形式为:
私有仓库的IP地址:端口号/镜像名称
docker tag python:3.8 172.17.0.2:5000/python:3.8
# docker images,多了一个镜像
通过Docker Registry工具上传Docker镜像时,只能通过https方式进行所以要在 /etc/docker/daemon.json 加入:
sudo vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://xxxx.mirror.aliyuncs.com"],
"insecure-registries":["172.17.0.2:5000"],
}
# esc -> :wq -> enter
sudo systemctl daemon-reload
sudo systemctl restart docker
docker ps
重载配置文件并重启docker服务,由于设置了–restart=always,docker重启,register也会重启,可以通过docker ps命令查看。
通过push命令上传该镜像到私有仓库,并查看
docker push 172.17.0.2:5000/python:3.8
curl http://172.17.0.2:5000/v2/_catalog
6、使用本地仓库的镜像
首先通过 rmi 镜像ID(或镜像名:tag),删除从官方拉取的python镜像,并通过docker images查看,然后从本地仓库拉取镜像,并查看:
docker pull 172.17.0.2:5000/python:3.8
docker images
7、其他操作
查看仓库内的镜像
curl http://172.17.0.2:5000/v2/_catalog
查看某个镜像的版本列表
curl http://172.17.0.2:5000/v2/python/tags/list
查看私有仓库的配置
docker exec -it registry sh -c 'cat /etc/docker/registry/config.yml'
删除私有仓库内的镜像
???
镜像
镜像的结构
镜像的原理是利用 Union FS 的技术,将其设计为分层存储的架构,由多层文件系统联合组成。
构建时会逐层构建,前一层是后一层的基础。
- 方便扩展:如果通过dockerfile制作镜像时,尽量把不变的放前面,比如环境的安装,环境变量设置等,把可能会变的步骤放后边,比如代码上传,启动执行命令等;
- 共享资源:比如我们基于Ubuntu18.04制作两个镜像,一个java镜像一个python镜像,这两个镜像就可以共用ubuntu18.04这个镜像层。
拉取镜像
通过如下命令拉取镜像,默认的地址是 Docker Hub 的地址,也可以通过配置修改默认地址,标签默认是 latest;
docker pull [仓库IP:port] 仓库名[标签]
两种制作方式
以制作java镜像,并上传代码到镜像为例:
1、 通过run命令启动一个以ubuntu为镜像的容器,然后进入运行的容器中安装java环境、配置环境变量,并通过docker cp命令把本地代码上传到容器里,最后通过docker commit命令将容器创建为一个新的镜像。
2、 编写Dockerfile 创建一个新的镜像。
推荐使用Dockerfile方式:
- commit方式生成的镜像是一种黑箱操作后的镜像,难以描述镜像的具体信息,所以很难做到维护、拓展、复用;
- commit 方式生成的镜像如果再拓展,之前的镜像无法改变,导致镜像越来越臃肿。
基于ubuntu18.04镜像制作一个带有java1.8环境的镜像
cd /usr/dockerfiles
sudo vim dockerfiles
### dockerfile
FROM 120.133.xx.xxx:5000/ubuntu:18.04
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
ADD jdk-8u144-linux-x64.tar.gz /usr/local/java/
ENV JAVA_HOME /usr/local/java/jdk1.8.0_144
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH
COPY ./VideoSearch/ /usr/VideoExtract/VideoSearch/
COPY ./lusi_workspace/ /usr/VideoExtract/lusi_workspace/
ENV LANG C.UTF-8
RUN cp /usr/VideoExtract/VideoSearch/videosearch.conf /etc/ld.so.conf.d/ && ldconfig
-
FROM:dockerfile中必备的,必须是第一条的指令,用来指定一个基础镜像,在其基础上进行后面的定制,基础镜像可以是mysql、redis等的服务镜像,也可以是java、python等的语言镜像,也可以是ubuntu、centos等的系统镜像;也可以指定空镜像scratch ,用来跑不需要任何环境支持的服务,比如go语言开发的微服务。不指明镜像仓库时默认用官方的镜像仓库,也可以像上面一样用我已经构建好的镜像仓库;
-
RUN:执行命令 ,因为每运行一次RUN,镜像就会多一层,因此多个RUN建议合并,用 \ 和 &&连接;
-
COPY:宿主机的文件复制到镜像内,源路径也可以使用通配符,比如COPY hom*、COPY hom?.txt,源文件的各种元数据都会保留,比如读写修改权限和文件修改时间等;
-
ADD:和COPY功能类似,但是在复制压缩格式的文件时,会自动解压缩到镜像内,并删除压缩包;
-
CMD :容器启动的时候执行的命令,也可以在docker run命令中指定,有两种形式,一种是 CMD <命令>,另一种是 CMD [“可执行文件”, “参数1”, “参数2”…],一般推荐第二种形式,比如 :
CMD [ "sh", "-c", "echo $HOME" ]
-
ENTRYPOINT :代替 CMD,但是可以在启动时指定 ENTRYPOINT 里的更多参数,比如
ENTRYPOINT [ “python”, “text.py” ],docker run 的时候可以在命令末端写成 -i,从而保持python的
输出; -
ENV:设置环境变量,可以用ENV KEY VALUE 或者 ENV KEY=VALUE;
-
VOLUME :创建一个或多个挂载点,VOLUME /data 或 VOLUME ["/data1","/data2"],指令会将容器内的/data目录和宿主机器的某个路径进行挂载,但是不可以在这里挂载到指定宿主机器的路径,要想指定需要在docker run启动容器时指定,并会覆盖掉这条指令。可以通过 dokcer inspect 容器名(容器ID)查看挂载情况;
-
EXPOSE :声明要暴露的端口,只是声明,为了让使用者理解镜像,真正生效需要在docker run时通过p参数指定;
-
WORKDIR:指定工作路径,为下一条命令做准备,dockerfile中不能RUN cd /data 再执行data下的命令,因此需要 WORKDIR /data 去选择;
-
USER:指定当前用户
-
HEALTHCHECK :设置检查容器健康状况的命令,有interval、timeout和cmd参数,也可以通过HEALTHCHECK NONE屏蔽基础镜像设定的健康检查命令;在docker ps 可以查看健康状态;
-
ONBUILD :当他是基础镜像被别的dockerfile from时,会执行。
-
ARG:设置 DockerFile 中的 环境变量,可以 ARG KEY VALUE 或者 ARG KEY=VALUE;在 FROM 前设置的只能在 FROM 命令里用,FROM 后设置的 可以在 FROM 包含的层用;
ARG DOCKER_USERNAME=library FROM ${DOCKER_USERNAME}/alpine
-
LABEL:给镜像以键值对的形式添加一些元数据,比如 该 Dockerfile 的作者,邮箱等;
LABEL authors="Ezrealer"
PS:建议在每个Dockerfile中加上如下指令,来保证容器的时区是中国时区,否则会和中国时区差8小时。
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
制作镜像的常用demo
1、apt-get 更换 到国内源
官方的python3.8镜像试用的Linux版本是Debian,因此在apt 安装时,为了保证速度,最好更换apt源为国内的阿里源;
注意最后一步清理 apt 留下的缓存
# 在dockerfile的目录下新建 sources.list 文件,写入
deb http://mirrors.aliyun.com/debian buster main
deb http://mirrors.aliyun.com/debian buster-updates main
# 在dockerfile中写入
RUN cp ./sources.list /etc/apt
RUN apt-get clean -y && apt-get update -y
2、下载与安装 Redis
注意最后一步 清理 apt 安装包;
FROM debian:stretch
RUN set -x; buildDeps='gcc libc6-dev make wget' \
&& apt-get update \
&& apt-get install -y $buildDeps \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
&& mkdir -p /usr/src/redis \
&& tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
&& make -C /usr/src/redis \
&& make -C /usr/src/redis install \
&& rm -rf /var/lib/apt/lists/* \
&& rm redis.tar.gz \
&& rm -r /usr/src/redis \
&& apt-get purge -y --auto-remove $buildDeps
代码放在Docker里面还是外面的方案
- dockerfile中通过RUN或者CMD指令执行pull命令,连接git代码管理;
- 直接在dockerfile中执行COPY,把代码上传到镜像里;
- 挂载到本地;
制作镜像的tips
-
如果镜像很复杂,尽量拆分为基础镜像(系统)、和应用镜像(程序),比如一个想制作一个爬虫镜像,可以先制作一个python镜像,在以python镜像为基础镜像制作爬虫应用镜像;
-
构建镜像时,和其他镜像有相同的层时会直接用缓存(会比对基础镜像所有生成的子镜像),因此尽量把不长改动的层放前面;
-
每执行一次 RUN 会构建新的一层,所以建议使用&&来连接多个 RUN 命令,并用反斜杠分成多行;
-
apt-get安装的推荐方式:
RUN apt-get update && \ apt-get install -y package && \ rm -rf /var/lib/apt/lists/*
-
ENV也会产生中间层,所以可以都合并到RUN里
RUN export ADMIN_USER="mark" \ && echo $ADMIN_USER > ./mark \ && unset ADMIN_USER
-
COPY或ADD时,源路径和目标路径都加反斜线 " \ "
-
如果不想复制某些文件,可以写一个 .dockerignore ,语法和 .gitignore 一样;
-
尽可能使用当前官方仓库作为你构建镜像的基础。推荐使用 Alpine 镜像,因为它被严格控制并保持最小尺寸(目前小于 5 MB),但它仍然是一个完整的发行版。
更多请参考:
- https://yeasy.gitbook.io/docker_practice/appendix/best_practices
构建镜像的命令
docker build -t java:8 -f /usr/dockerfiles/dockerfile .
-
-t:指定镜像的名称:标签;
-
-f:指定要使用dockerfile的路径,如果不指定,默认会在 上下文目录下的 DockerFile文件作为 dockerfile;
-
最后面的点:指定dockerfile要使用的构建镜像上下文,简单的说就是COPY命令的根路径,COPY中源路径参数的 ./ 就是build指令这个点指定的路径,也可以写成绝对路径;
此外,还可以指定一些参数,比如指定CPU的使用权重、配额、周期、内存最大值、swap最大值、ulimit,netwokd模式等。
其他操作
1、删除镜像
docker rmi 镜像名
docker rmi 镜像ID
# 批量删除所有 redis 镜像
$ docker image rm $(docker image ls -q redis)
2、 查看镜像创建历史
docker history 镜像名
3、镜像文件的导入与导出
docker save -o filename.tar 镜像名
docker load -i 文件名
# 利用docker export的容器文件生成镜像
docker import filename.tar 818/ubuntu:1804
4、查看镜像
docker images
# 根据仓库名查看镜像
docker images 仓库名
# 查看所有镜像的 ID
docker images -q
运行容器
启动容器
通过如下命令将我们上述构建的镜像启动起来
# docker run 参数 镜像 CMD
docker run -itd --name="extracvideo" java:8 java -jar testexe.jar
参数:
- -d:后台启动容器,并返回容器ID
- -i:交互模式运行容器,和-t一起用
- -t:为容器分配一个伪终端
- -p:端口映射,主机端口:容器端口
- –name:容器名称
- -e:环境变量
- –env-file:从指定文件读入环境变量
- -m:容器使用内存的最大值
- -v:绑定一个卷,宿主机路径:容器内路径
这里在启动时加了参数 -itd,因为如果启动容器时不加命令,或者命令执行完毕,容器会立即停止运行,加入 -itd参数后,即使没有输入命令,容器也不会退出。
启动一个容器,如果报错如下:
docker: Error response from daemon: endpoint with name extractvideo_90 already exists in network bridge.
可能因为删容器时,网络的占用还残留在docker服务中,需要手动清除一下:
docker network inspect bridge
# 从Containers 中找到网络占用的container_name
docker network disconnect --force bridge container_name
启动步骤
1、当执行 docker run 时,首先检查本地是否存在指定镜像,不存在则会到共有仓库pull;
2、启动后,为该容器分配一个文件系统,并在只读的镜像层外会挂载一个读写层;
3、接着从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去,从地址池配置一个 ip 地址给容器;
4、然后执行指定的命令,执行完毕后容器会被终止;
5、当容器被删除时,读写层也不会保留,所以对容器读写时,如果希望持久化内容,则要和宿主机器做一个挂载。
其他操作
1、 查看容器详情
docker inspect 容器ID
2、 查看容器内进程信息
docker top 容器ID
3、查看容器日志
docker logs 容器ID
4、 容器内外的复制
docker cp 主机路径 容器ID:容器内路径
docker cp 容器ID:容器内路径 主机路径
5、 进入容器
docker exec -it 容器ID /bin/bash
# 回到宿主机器
ctrl + p + q
6、 终止容器
docker stop 容器ID
7、删除容器
# 根据ID
docker rm 容器ID
# 强行删除(正在运行)
docker rm -f 容器ID
# 清理停止运行的容器
docker container prune
8、导入导出
# 导出
docker export -o filename.tar 容器ID
# 导入容器文件为镜像
docker import filename.tar 818/ubuntu:1804
9、查看容器的Linux版本
只能用 cat /etc/issue命令,用 uname -a 或者 cat /proc/version 则看到的是宿主机器的版本
docker exec -it 容器id /bin/bash
cat /etc/issue
PS:我们最好进到容器里查看一下容器的IP、系统时间等,避免运行服务时出现其他错误。
容器的数据管理
由于容器删除时,内部的数据会消失,所以对容器的读写,建议另外管理,一般有两种方式,分别是 数据卷 和 挂载主机目录;
数据卷
容器挂在到数据卷,就像服务器挂在到硬盘一样,数据卷可以被多个容器共享;
1、创建数据卷
docker volume create my-vol
2、查看所有数据卷
docker volume ls
3、查看某个数据卷的详细信息
docker volume inspect my-vol
4、删除数据卷
docker volume rm my-vol
5、清理无主的数据卷
docker volume prune
6、启动容器时挂在数据卷
docker run -d --mount source=my-vol,target=/usr/GitCodes
挂在到主机目录
docker run -v /usr/mda_registry:/var/lib/registry
# 或者
docker run --mount type=bind,source=/usr/mda_registry,target=/var/lib/registry
Docker网络
参考:https://www.jianshu.com/p/bf8eb25d180e
外部访问容器
1、Host 模式(容器和宿主机器共用网络)
在 docker run 命令 加入 --network host 参数后,启动的容器则试用了host网络模式,host网络模式有如下特性:
-
容器与主机在相同的网络命名空间下面,使用相同的网络协议栈,容器可以直接使用主机的所有网络接口
-
host 模式 不能使用端口映射和自定义路由规则,这些都与主机一致,-p 与-icc 参数是无效的
-
host 模式下面的网络模型是最简单和最低延迟的模式,容器进程直接与主机网络接口通信,与物理机性能一致
2、端口映射
容器启动时,通过 p 参数 ,可以将 宿主机器的端口和容器绑定,可以同时绑定 1个 或 多个端口;
docker run -d -p 80:80 -p 443:443 nignx
容器互联
1、新建网络
docker network create -d bridge my-net
2、将容器连接到网络
docker run -it --rm --name busybox1 --network my-net busybox sh
docker run -it --rm --name busybox2 --network my-net busybox sh
3、进入 busybox1 ,ping busybox2 ,证明互联成功
4、如果需要 多个容器互联,建议 Docker Compose
配置容器的DNS
1、配置全部容器的 DNS
vim /etc/docker/daemon.json
{
"dns" : [
"114.114.114.114",
"8.8.8.8"
]
}
2、配置单个容器的 DNS
# 配置主机名
-h HOSTNAME or --hostname=HOSTNAME
# 添加 DNF 服务器 到 容器
--dns=IP_ADDRESS
# 设置容器的搜索域
--dns-search=DOMAIN
容器的日志
两种日志
Docker的日志分为 容器引擎运行的日志 和 容器内的服务产生的日志,容器引擎运行的日志可以通过如下命令查看:
journalctl -u docker
服务日志
1、查看
docker logs 容器ID(名称)
# 跟踪输出
docker logs -f 容器ID(名称)
# 显示时间戳
docker logs -t 容器ID(名称)
通过cat或tail指令查看日志文件,路径在:
/var/lib/docker/containers/容器ID/容器ID-json.log
/var/lib/docker/containers/容器ID/ 路径下有如下文件:
checkpoints
config.v2.json:容器配置信息
e687940d6b40e9e5d5812e04a694342ff0d839050de0b7f52dd2d3964f6baa9c-json.log :容器日志
hostconfig.json
hostname :容器的主机名
hosts :容器的hosts
mounts :挂载
resolv.conf:DNS服务器设置
2、日志驱动
有 json-file(默认),loca,syslog,Journald ,可通过docker info 和docker inspect 容器ID查看总设置的日志驱动和某个容器的日志驱动;
可以在daemon.json里设置,其中:
max-size 是单个日志文件最大体积,max-file 是一个容器产生的最多日志文件数量
vim /etc/docker/daemon.json
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file":"1",
}
}
#systemctl daemon-reload
#systemctl restart docker
也可以在 docker run命令中指定某个容器的日志驱动:
docker run -itd --log-driver json-file --log-opt max-size=10m --log-opt max-file=3 java8
容器常用命令汇总
-
容器实例相关 : docker [ run | start | stop | restart | kill | rm | attach | exec | pause | unpause | cp ]
-
容器查看信息 : docker [ stats | ps | inspect | top | logs | wait | export | port | diff ]
-
镜像相关 — docker [ images | rmi | tag | build | commit | history | save | import ]
-
镜像仓库相关 : docker [ login | pull | push | search ]
-
容器服务相关 : docker [ info | version | events ]
docker stats # 查看每个容器占用的CPU、内存、IO等资源
docker inspect # 深入容器内部获取容器所有信息
docker logs # 查看容器的日志(stdout/stderr)
docker events # 得到docker服务器的实时的事件
docker port # 显示容器的端口映射
docker top # 显示容器的进程信息
docker diff # 显示容器文件系统的前后变化
docker history # 显示生成一个镜像的历史命令
docker system df # 查看镜像、容器、数据卷所占用的空间
docker create # 创建一个容器但是不启动它
docker run # 创建并启动一个容器
docker stop # 停止容器运行,发送信号SIGTERM
docker start # 启动一个停止状态的容器
docker restart # 重启一个容器
docker rm # 删除一个容器
docker kill # 发送信号给容器,默认SIGKILL
docker attach # 连接(进入)到一个正在运行的容器
docker wait # 阻塞一个容器,直到容器停止运行
docker ps # 显示状态为运行(Up)的容器
docker ps -a # 显示所有容器,包括运行中(Up)的和退出的(Exited)
docker cp # 从容器里向外拷贝文件或目录
docker export # 将容器整个文件系统导出为一个tar包,不带layers、tag等信息
docker exec # 在容器里执行一个命令,可以执行bash进入交互式。
docker images # 显示本地所有的镜像列表
docker import # 从一个tar包创建一个镜像,往往和export结合使用
docker build # 使用Dockerfile创建镜像(推荐)
docker commit # 从容器创建镜像
docker rmi # 删除一个镜像
docker load # 从一个tar包创建一个镜像,和save配合使用
docker save # 将一个镜像保存为一个tar包,带layers和tag信息
docker tag # 为镜像起一个别名
docker rmi $(docker images -f dangling=true -q) # 删除不带标签的镜像
Docker 相关插件
Nexus 3
在企业中把内部的一些工具包放入 Nexus 中是比较常见的做法,最新版本 Nexus3.x 全面支持 Docker 的私有镜像,用如下命令即可启动 Nexus 3 容器;
docker run -d --name nexus3 --restart=always \
-p 8081:8081 \
--mount src=nexus-data,target=/nexus-data \
sonatype/nexus3
使用 Nexus3.x 一个软件来管理 Docker , Maven , Yum , PyPI 等是一个明智的选择。
Docker Buildx
一款扩展docker 命令的插件;
Docker Compose
1、定义
Compose 项目是 Docker 官方的开源项目,负责实现对 Docker 容器集群的快速编排。
Docker Compose 通过一个单独的 docker-compose.yml 模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)。
Compose 的两个重要概念是 服务 与 项目 ,服务是一个或一组 运行相同镜像的 容器;项目是多个服务组成的,在 docker-compose.yml 中定义
2、安装 与卸载
sudo pip install -U docker-compose
sudo pip uninstall docker-compose
3、docker-compose.yml 模板
build:Dockerfile 所在文件夹的路径,绝对路径或者 相对于 docker-compose.yml 文件的相对路径都可;
command:容器启动后默认执行命令(可覆盖);
depends_on:设定不同服务的依赖,从而指定先后启动顺序,比如下面设置就会先启动db和redis服务,后启动web服务;
version: "3"
services:
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
depends_on:
- db
- redis
links:
- db
db:
image: postgres
4、启动 compose 项目
下面命令 自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作。
docker-compose up [options] [SERVICE...]
docker-compose up -d 项目名 # 后台运行,生产环境使用
5、动态扩容缩容
在 docker-compose scale 命令中 通过指定服务的数量来实现;
docker-compose scale web=3 db=2
Swarm mode
1、定义
swarm 集群,具有容错能力的去中心化设计、内置服务发现、负载均衡、路由网格、动态伸缩、滚动更新、安全传输等。
2、概念
节点:分为 管理节点 和 工作节点 (可重合);管理节点用来执行 docker swarm 命令,工作节点 用来执行管理节点下发的任务;
任务:一个单一的容器;
服务:一组任务的集合,有两种服务模式,replicated services 与 global services ,前者 根据设定决定每个节点运行多少个任务,后者每个节点运行一个任务;
3、操作
初始化集群、增加工作节点、部署服务、管理配置信息、滚动升级等。
Docker Swarm 集群方案
https://mp.weixin.qq.com/s?__biz=MzIzOTQzNDIyOA==&mid=2247483764&idx=1&sn=c36796de85fb9af8c86104f4aeb68162&chksm=e92b61efde5ce8f9e7060081e3812dbb03bc0cd10af277b5a4c451083ba871ef9cfce211a0ee&scene=21#wechat_redirect
Docker 错误排查
docker restart 报错
2020-09-14T13:00:04+0800 [Launcher,1829/stderr] Exception ignored when trying to write to the signal wakeup fd:
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/twisted/internet/_signals.py", line 56, in noopSignalHandler
def noopSignalHandler(*args):
BlockingIOError: [Errno 11] Resource temporarily unavailable
2020-09-14T13:00:04+0800 [Launcher,1327/stderr] Exception ignored when trying to write to the signal wakeup fd:
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/twisted/internet/_signals.py", line 56, in noopSignalHandler
def noopSignalHandler(*args):
BlockingIOError: [Errno 11] Resource temporarily unavailable
2020-09-14T13:00:04+0800 [Launcher,3324/stderr] Exception ignored when trying to write to the signal wakeup fd:
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/twisted/internet/_signals.py", line 56, in noopSignalHandler
def noopSignalHandler(*args):
BlockingIOError: [Errno 11] Resource temporarily unavailable
2020-09-14T13:00:04+0800 [Launcher,1327/stderr] Exception ignored when trying to write to the signal wakeup fd:
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/twisted/internet/_signals.py", line 56, in noopSignalHandler
def noopSignalHandler(*args):
BlockingIOError: [Errno 11] Resource temporarily unavailable
2020-09-14T13:00:04+0800 [Launcher,4392/stderr] Exception ignored when trying to write to the signal wakeup fd:
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/twisted/internet/_signals.py", line 56, in noopSignalHandler
def noopSignalHandler(*args):
BlockingIOError: [Errno 11] Resource temporarily unavailable
2020-09-14T13:00:04+0800 [Launcher,1084/stderr] Exception ignored when trying to write to the signal wakeup fd:
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/twisted/internet/_signals.py", line 56, in noopSignalHandler
def noopSignalHandler(*args):
BlockingIOError: [Errno 11] Resource temporarily unavailable
Another twistd server is running, PID 1
This could either be a previously started instance of your application or a
different application entirely. To start a new one, either run it in some other
directory, or use the --pidfile and --logfile parameters to avoid clashes.
Another twistd server is running, PID 1
Docker 相关资源
(参考崔庆才)https://cuiqingcai.com/5438.html
官方网站:https://www.docker.com
GitHub:https://github.com/docker
Docker Hub:https://hub.docker.com
官方文档:https://docs.docker.com
DaoCloud:http://www.daocloud.io
中文社区:http://www.docker.org.cn
中文教程:http://www.runoob.com/docker/docker-tutorial.html
Docker 技术入门与实战:https://yeasy.gitbooks.io/docker_practice
更多推荐
所有评论(0)