Docker 知识汇总

Docker 汇总

在这里插入图片描述

1. 简介

docker官网
docker文档
阿里云镜像搜索
查询所有镜像

容器话技术很早就出现过,如 OpenVZ,LXC,RKT等

1.1 容器是什么

虚拟机

虚拟机代表: VMWare, OpenStack, 模拟运行一整套操作系统(包括内核, 应用运行态环境和其它系统环境)和跑在上面的应用.

容器

container,独立运行的一个或者一组应用, 以及他们必需的运行环境。 容器是Pass(platform-as-a-service)的一种体现。 通俗的说容器是一种沙盒技术或者说是个轻量级的虚拟机。

容器是为了解决 “在切换运行环境时,如何保证软件能够正常运行” 的问题。

Docker入门

1.2 Docker是什么

​ 源于百度 - Docker 是一个开源的应用容器引擎, 让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中, 然后发布到任何流行的 Linux或Windows 机器上, 也可以实现虚拟化。容器是完全使用沙箱机制, 相互之间不会有任何接口。

​ 通俗的讲, 容器可以看成是一个轻量级的虚拟机, Docker或是用于管理容器的一种引擎技术。 曾经的Java是提出的是"Write Once, Run Anywhere", 而现在的Docker提出的是"Build, Skip and Run Any APP, Anywhere"

其它:

  • go语言实现

  • 打出来的包叫做镜像, 镜像运行时叫做容器。Docker解决了运行环境和配置问题, 方便发布, 也就方便做持续集成。

  • Docker是基于Linux 64bit的, 在32位机器上无法运行

Docker详细

docker有两个版本 社区版(Community edition, CE)和企业版(Enterprise edition, EE)。企业版包含了一些收费服务,一般我们都用社区版。

在这里插入图片描述

1.3 优势缺点

优势

  • 有助于Microservices的落地和部署
  • 充分利用物理机资源,同时能够整合服务器资源
  • 提高开发效率,测试效率,部署效率,有利于DevOps的落地,CICD
  • 云原生落地,应用更好地迁移

缺点

  • 缺乏成熟的管理工具。

1.4 底层技术支持

Container是一种轻量级的虚拟化技术,不用模拟硬件创建虚拟机。
Docker是基于Linux Kernel的Namespace、CGroups、UnionFileSystem等技术封装成的一种自定义容器格式,从而提供一套虚拟运行环境。

  • Namespace:用来做隔离的,比如pid[进程]、net[网络]、mnt[挂载点]等
  • CGroups: Controller Groups用来做资源限制,比如内存和CPU等
  • Union file systems:用来做image和container分层

2. 环境安装

docker 是基于docker engin的,类似于java基于jvm一样。所以是跨平台的。window, Linux, Mac等都可以。

建议在CentOs系统上进行docker的使用。

CentOs 安装 :

  • VMWare 安装虚拟机
  • VirtualBox + vagrant 安装 centOs7

具体安装步骤百度。

docker安装在Linux的目录为 /var/lib/docker

2.1 安装Docker

# 可以查看docker的版本
yum list docker-ce --showduplicates | sort -r

01 卸载之前的docker
	sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
                  
02 安装必要的依赖
	sudo yum install -y yum-utils device-mapper-persistent-data lvm2
    
03 设置docker仓库
    yum 源的设置
	sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

    docker仓库设置
    [访问这个地址,使用自己的阿里云账号登录,查看菜单栏左下角,发现有一个镜像加速器:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors]

04 安装docker
	sudo yum install -y docker-ce docker-ce-cli containerd.io
	
05 启动docker
	sudo systemctl start docker
	
06 测试docker安装是否成功
	sudo docker run hello-world

登录自己的阿里云账号,找到镜像加速器地址

1. 安装/升级Docker客户端
推荐安装1.10.0以上版本的Docker客户端,参考文档docker-ce

2. 配置镜像加速器
针对Docker客户端版本大于 1.10.0 的用户

您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://8fij84na.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

ubunto 安装

# 下载安装
apt-get -y install docker.io
# 镜像加速器 如上自行设置
# 设置开机自动重启
systemctl start docker && systemctl enable docker

2.2 搭建自己的Harbor私有仓库

​ Harbor是由VMware公司开源的企业级的Docker Registry管理项目,它包括权限管理(RBAC)、LDAP、日志审核、管理界面、自我注册、镜像复制和中文支持等功能。

2.2.1 环境准备

​ Harbor的所有服务组件都是在Docker中部署的,所以官方安装使用Docker-compose快速部署,所以我们需要安装Docker、Docker-compose。由于Harbor是基于Docker Registry V2版本,所以就要求Docker版本不小于1.10.0,Docker-compose版本不小于1.6.0

2.2.2 安装包
# 下载离线安装包
$ wget https://ghproxy.com/https://github.com/goharbor/harbor/releases/download/v2.6.2/harbor-offline-installer-v2.6.2.tgz

# 解压到当前目录
$ tar xvf harbor-offline-installer-v2.6.2.tgz

$ cd harbor

# 拷贝模板配置文件
$ cp harbor.yml.tmpl harbor.yml

# 进入文件 修改相关信息和下面的认证信息相匹配
$ vim harbor.yml

harbor.yml 修改的内容如下

在这里插入图片描述

hostname: hj.harbor.org

http:
  # port for http, default is 80. If https enabled, this port will redirect to https port
  port: 9080
  
https:
  # https port for harbor, default is 443
  port: 9443
  # The path of cert and key files for nginx
  certificate: /home/hj/harbor/cert/hj.harbor.org.crt
  private_key: /home/hj/harbor/cert/hj.harbor.org.key
  
harbor_admin_password: 123456

# Harbor DB configuration
database:
  # The password for the root user of Harbor DB. Change this before any production use.
  password: 123456
  
# The default data volume
data_volume:  /home/hj/harbor/data
2.2.3 生成认证(https)
#!/bin/bash

# 需要修改的地方
domainname="hj.harbor.org"
domainport="9443"
harbordir="/home/hj/harbor"
gencertdir="$harbordir/cert"

# 生成证书的路径
mkdir -p $gencertdir
cd $gencertdir

openssl genrsa -out ca.key 4096

openssl req -x509 -new -nodes -sha512 -days 3650 \
 -subj "/C=CN/ST=GuangDong/L=GuangZhou/O=example/OU=Personal/CN=$domainname" \
 -key ca.key \
 -out ca.crt

openssl genrsa -out $domainname.key 4096

openssl req -sha512 -new \
    -subj "/C=CN/ST=GuangDong/L=GuangZhou/O=example/OU=Personal/CN=$domainname" \
    -key $domainname.key \
    -out $domainname.csr

cat > v3.ext <<-EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1=$domainname
DNS.2=www.$domainname
EOF

openssl x509 -req -sha512 -days 3650 \
    -extfile v3.ext \
    -CA ca.crt -CAkey ca.key -CAcreateserial \
    -in $domainname.csr \
    -out $domainname.crt

openssl x509 -inform PEM -in $domainname.crt -out $domainname.cert

if [ "$domainport" == "443" ]
then

  mkdir -p /etc/docker/certs.d/$domainname/
  
  cp $domainname.cert /etc/docker/certs.d/$domainname/
  cp $domainname.key /etc/docker/certs.d/$domainname/
  cp ca.crt /etc/docker/certs.d/$domainname/
  cp ca.crt /etc/pki/ca-trust/source/anchors

else
  mkdir -p /etc/docker/certs.d/$domainname:$domainport/
  
  cp $domainname.cert /etc/docker/certs.d/$domainname:$domainport/
  cp $domainname.key /etc/docker/certs.d/$domainname:$domainport/
  cp ca.crt /etc/docker/certs.d/$domainname:$domainport/
  cp ca.crt /etc/pki/ca-trust/source/anchors

fi

update-ca-trust extract
systemctl restart docker
2.2.4 安装Harbor
$ ./prepare
$ ./install.sh

在这里插入图片描述

在这里插入图片描述

2.2.5 启动 ok
# 可以见得启动了很多的容器 包括redis,所以安装harbor 最好是干净的环境,比如,若环境中已经存在了 redis 这里的redis就会提示容器名已经占用了
$ docker-compose ps

在这里插入图片描述

访问即可,用户名/密码:admin/123456

在这里插入图片描述

2.2.6 开机自动重启
# 注意修改对应的启动目录 一下内容为新建
$ vim /usr/lib/systemd/system/harbor.service

[Unit]
Description=Harbor
After=docker.service systemd-networkd.service systemd-resolved.service
Requires=docker.service
Documentation=http://github.com/vmware/harbor

[Service]
Type=simple
Restart=on-failure
RestartSec=5
ExecStart=/usr/local/bin/docker-compose -f /home/hj/harbor/docker-compose.yml up
ExecStop=/usr/local/bin/docker-compose -f /home/hj/harbor/docker-compose.yml down

[Install]
WantedBy=multi-user.target
sudo systemctl enable harbor
sudo systemctl start harbor
2.2.7 客户端配置

配置域名

# 若真实存在域名,则不需要配置
$ sudo vim /etc/hosts
192.168.8.121 hj.harbor.org

配置客户端docker文件

$ vim /etc/docker/daemon.json

# 增加下面内容,harbor 默认端口为 80 情况,如果非 80,需要在 IP 后加端口
# {"insecure-registries":["harbor服务端IP"]}

{
    "insecure-registries":["hj.harbor.org:9080"],
    "insecure-registries":["hj.harbor.org:9443"]
}

sudo systemctl daemon-reload
sudo systemctl restart docker

登录操作

$ docker login hj.harbor.org
Username: admin
Password:
Login Succeeded

#或者
$ docker login hj.harbor.org -u admin -p 具体密码
$ docker tag nginx hj.harbor.org/hj/nginx

$ docker push hj.harbor.org/hj/nginx
2.2.X 附录:配置文件

配置文件中的内容都是安装 dockerHarbor 用到的,其中有 mysql,redis 这些,这些是它需要使用的

## Configuration file of Harbor

_version = 1.5.0
# hostname设置访问地址,可以使用ip、域名,不可以设置为127.0.0.1或localhost
hostname = 116.62.23.147

# 访问协议,默认是http,也可以设置https,如果设置https,则nginx ssl需要设置on
ui_url_protocol = http

#Maximum number of job workers in job service
max_job_workers = 50

#Determine whether or not to generate certificate for the registry's token.
#If the value is on, the prepare script creates new root cert and private key
#for generating token to access the registry. If the value is off the default key/cert will be used.
#This flag also controls the creation of the notary signer's cert.
customize_crt = on

#The path of cert and key files for nginx, they are applied only the protocol is set to https
ssl_cert = /data/cert/server.crt
ssl_cert_key = /data/cert/server.key

#The path of secretkey storage
secretkey_path = /data

#Admiral's url, comment this attribute, or set its value to NA when Harbor is standalone
admiral_url = NA

#Log files are rotated log_rotate_count times before being removed. If count is 0, old versions are removed rather than rotated.
log_rotate_count = 50
#Log files are rotated only if they grow bigger than log_rotate_size bytes. If size is followed by k, the size is assumed to be in kilobytes.
#If the M is used, the size is in megabytes, and if G is used, the size is in gigabytes. So size 100, size 100k, size 100M and size 100G
#are all valid.
log_rotate_size = 200M

#Config http proxy for Clair, e.g. http://my.proxy.com:3128
#Clair doesn't need to connect to harbor ui container via http proxy.
http_proxy =
https_proxy =
no_proxy = 127.0.0.1,localhost,ui

#NOTES: The properties between BEGIN INITIAL PROPERTIES and END INITIAL PROPERTIES
#only take effect in the first boot, the subsequent changes of these properties
#should be performed on web ui

#************************BEGIN INITIAL PROPERTIES************************
# 邮件设置,发送重置密码邮件时使用
email_identity =

email_server = smtp.mydomain.com
email_server_port = 25
email_username = sample_admin@mydomain.com
email_password = abc
email_from = admin <sample_admin@mydomain.com>
email_ssl = false
email_insecure = false

# 启动Harbor后,管理员UI登录的密码,默认是Harbor12345
harbor_admin_password = 950828

# 认证方式,这里支持多种认证方式,如LADP、本次存储、数据库认证。默认是db_auth,mysql数据库认证
auth_mode = db_auth

# LDAP认证时配置项
# ldap_url = ldaps://ldap.mydomain.com

#ldap_searchdn = uid=searchuser,ou=people,dc=mydomain,dc=com
#ldap_search_pwd = password
# ldap_basedn = ou=people,dc=mydomain,dc=com
#ldap_filter = (objectClass=person)
# ldap_uid = uid
#the scope to search for users, 0-LDAP_SCOPE_BASE, 1-LDAP_SCOPE_ONELEVEL, 2-LDAP_SCOPE_SUBTREE
# ldap_scope = 2
#Timeout (in seconds)  when connecting to an LDAP Server. The default value (and most reasonable) is 5 seconds.
# ldap_timeout = 5
#Verify certificate from LDAP server
# ldap_verify_cert = true
#The base dn from which to lookup a group in LDAP/AD
# ldap_group_basedn = ou=group,dc=mydomain,dc=com
#filter to search LDAP/AD group
# ldap_group_filter = objectclass=group
#The attribute used to name a LDAP/AD group, it could be cn, name
# ldap_group_gid = cn
#The scope to search for ldap groups. 0-LDAP_SCOPE_BASE, 1-LDAP_SCOPE_ONELEVEL, 2-LDAP_SCOPE_SUBTREE
# ldap_group_scope = 2

# 是否开启自注册
self_registration = on

# Token有效时间,默认30分钟
token_expiration = 30

# 用户创建项目权限控制,默认是everyone(所有人),也可以设置为adminonly(只能管理员)
project_creation_restriction = everyone

#************************END INITIAL PROPERTIES************************

#######Harbor DB configuration section#######

#The address of the Harbor database. Only need to change when using external db.
db_host = mysql

# mysql数据库root用户默认密码root123,实际使用时修改下
db_password = grg@123

#The port of Harbor database host
db_port = 13306

#The user name of Harbor database
db_user = root

##### End of Harbor DB configuration#######

#The redis server address. Only needed in HA installation.
#address:port[,weight,password,db_index]
redis_url = redis:16379

##########Clair DB configuration############

#Clair DB host address. Only change it when using an exteral DB.
clair_db_host = postgres

#The password of the Clair's postgres database. Only effective when Harbor is deployed with Clair.
#Please update it before deployment. Subsequent update will cause Clair's API server and Harbor unable to access Clair's database.
clair_db_password = password

#Clair DB connect port
clair_db_port = 5432

#Clair DB username
clair_db_username = postgres

#Clair default database
clair_db = postgres

##########End of Clair DB configuration############

#The following attributes only need to be set when auth mode is uaa_auth
uaa_endpoint = uaa.mydomain.org
uaa_clientid = id
uaa_clientsecret = secret
uaa_verify_cert = true
uaa_ca_cert = /path/to/ca.pem


### Docker Registry setting ###
#registry_storage_provider can be: filesystem, s3, gcs, azure, etc.
registry_storage_provider_name = filesystem
#registry_storage_provider_config is a comma separated "key: value" pairs, e.g. "key1: value, key2: value2".
#Refer to https://docs.docker.com/registry/configuration/#storage for all available configuration.
registry_storage_provider_config =

2.3 离线安装 Docker

官方地址下载地址:

https://download.docker.com/linux/static/stable/x86_64/docker-19.03.9.tgz 

解压:

tar -zxvf docker-19.03.9.tgz

解压的docker文件夹全部移动至/usr/bin目录

cp -p docker/* /usr/bin

将docker注册为系统服务

① 在/usr/lib/systemd/system/目录下,创建docker.service文件
② 编辑docker.service文件

[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Uncomment TasksMax if your systemd version supports it.
# Only systemd 226 and above support this version.
#TasksMax=infinity
TimeoutStartSec=0
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process
# restart the docker process if it exits prematurely
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
 
[Install]
WantedBy=multi-user.target
#重载unit配置文件
systemctl daemon-reload
#启动Docker
systemctl start docker
#设置开机自启
systemctl enable docker
#查看Docker状态
systemctl status docker
#查看Docker版本
docker version
docker -v                                                                                

2.4 docker-compose 离线安装

下载

https://github.com/docker/compose/releases/download/v2.2.2/docker-compose-linux-x86_64
sudo mv docker-compose-linux-x86_64 /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose -v

3. 常用命令

3.1 启动查看

sudo systemctl start docker    # 启动docker
sudo systemctl stop docker     # 停止docker
sudo systemctl enable docker   # 开机启动
docker version                 # 查看docker信息 client和server信息
docker stats                   # 查看容器资源使用情况
docker inspect container       # 查看容器详情
docker stop/start container    # 启动/停止容器

3.2 用户登录

docker login  # 登录docker官网 会有docker push的权限 前提是你要有账号 
3.2.1 使用阿里云docker hub
(1)登录到阿里云docker仓库
sudo docker login --username=itcrazy2016@163.com registry.cn-hangzhou.aliyuncs.com
(2)输入密码
(3)创建命名空间,比如itcrazy2016
(4)给image打tag
sudo docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/itcrazy2016/test-
docker-image:v1.0
(5)推送镜像到docker阿里云仓库
sudo docker push registry.cn-hangzhou.aliyuncs.com/itcrazy2016/test-docker-
image:v1.0
(6)别人下载,并且运行
docker pull registry.cn-hangzhou.aliyuncs.com/itcrazy2016/test-docker-
image:v1.0
docker run -d --name user01 -p 6661:8080 registry.cn-
hangzhou.aliyuncs.com/itcrazy2016/test-docker-image:v1.0
3.2.2 使用自己的docker hub
(1)访问github上的harbor项目
https://github.com/goharbor/harbor
(2)下载版本,比如1.7.1
https://github.com/goharbor/harbor/releases
(3)找一台安装了docker-compose[这个后面的课程会讲解],上传并解压
tar -zxvf xxx.tar.gz
(4)进入到harbor目录
修改harbor.cfg文件,主要是ip地址的修改成当前机器的ip地址
同时也可以看到Harbor的密码,默认是Harbor12345
(5)安装harbor,需要一些时间
sh install.sh
(6)浏览器访问,比如39.100.39.63,输入用户名和密码即可

3.3 镜像操作

  • 默认镜像都是从官网仓库拉取的
  • 在 /etc/docker/daemon.json 配置阿里云加速器,官方拉取太慢了
3.3.1 创建镜像
# 根据 Dockerfile 来构建一个镜像 推荐
# dockerfilePath 是目录路径 改目录下默认有 Dockerfile 文件
docker build -t <image name> <dockerfilePath>

# 将容器变为镜像 可以定制化镜像 缺点是容器的创建过程不知道 不推荐
docker commit <containerId> <ImageName>  
3.3.2 拉取镜像
# 1. 默认在官网仓库搜索镜像信息,OFFICIAL IMAGE 标签代表官方image
# 2. 镜像名: 镜像名:版本[TAG]
# 3. 默认拉取 latest 版本的镜像 即最新的

docker search <name>         # 根据名称 模糊搜索 从远程仓库找到需要的镜像 
docker pull <hello-world>    # 拉取镜像 从远程仓库拉取镜像到本地
常用镜像
docker pull openjdk:8
docker pull tomcat:8.0.30-jre8
3.3.3 查看镜像
# 列出本地所有的镜像
docker images  
docker image ls
# REPOSITORY    TAG      IMAGE ID   CREATED     SIZE 
# 镜像名         镜像版本   镜像ID     上次更新时间   镜像大小

# 查询指定镜像的配置信息
docker search <镜像名>

docker image inspect 容器名     # 查看镜像信息
3.3.4 删除镜像
docker image rm <imageId>
docker rmi -f <image name>            # 根据镜像名 从本地仓库删除该镜像
docker rmi -f $(docker image ls)      # 删除所有的镜像

docker system prune                   # 清理所有 慎用 暂时关闭的没有用到的都会清理掉 
3.3.5 别名镜像
docker tag <image name> <别名:版本>     # 创建镜像副本
3.3.6 推送镜像到仓库
# 需要先登录 设置仓库
# docker login 远程仓库host:port
# docker tag <image name> <harbor地址:port/目录/镜像名:版本>

# 若是镜像的名字不具有远程仓库的前缀 则推送到了默认的 github 的harbor仓库中
docker push <harbor地址:port/目录/镜像名:版本>                # 推送镜像到docker官网 前提是登录取得push权限
3.3.7 镜像的导入导出
# 将镜像导出成一个压缩文件
docker export <container id> > xxx.tar
docker save  <image id> > xxx.tar

# 可以将多个image打成一个文件
docker save -o images.tar postgres:9.6 mongo:3.4

# 导入文件为一个镜像
docker import - <new image name> < xxx.tar
docker load < xxx.tar

# 加载镜像
docker load -i mrcp-507-2e49eeae5025.tar
exportsave
针对的是容器针对的是镜像
导出的文件体积小导出的文件体积大
可以为镜像指定新名字不能对载入的镜像命名
不支持多个镜像打入一个包支持多个镜像打入一个包
export 导出(import 导入)是根据容器拿到的镜像,再导入时会丢失镜像所有的历史记录和元数据信息(即仅保存容器当时的快照状态),所以无法进行回滚操作。save 保存(load 加载)的镜像,没有丢失镜像的历史,可以回滚到之前的层(layer)。
docker export 的应用场景:主要用来制作基础镜像,比如我们从一个 ubuntu 镜像启动一个容器,然后安装一些软件和进行一些设置后,使用 docker export 保存为一个基础镜像。然后,把这个镜像分发给其他人使用,比如作为基础的开发环境。docker save 的应用场景:如果我们的应用是使用 docker-compose.yml 编排的多个镜像组合,但我们要部署的客户服务器并不能连外网。这时就可以使用 docker save 将用到的镜像打个包,然后拷贝到客户服务器上使用 docker load 载入。

3.4 容器操作

3.4.1 创建容器
# 根据镜像创建一个容器 若该镜像不存在本地,则从远程仓库拉取然后创建一个容器
docker run 
[-d]                             # -d 后台运行 Detached 模式, 默认是 Foreground 模式
[--rm]                           # 与-d 互斥,Foreground 模式 退出时自动清理
[-u]                             # 指定容器运行的 用户,命令RUN、CMD、ENTRYPOINT都将使用该用户
--name <container name>          # --name 启动的容器名
[-v <volName>:<containerPath>]   # -v 指定容器资源对应宿主机的地址
[--memory <size>]                # --memory 内存最大值
[--cpu-shares <num>]             # --cpu-shares 权重配比(相比于其它占的比列)
[--ip 192.168.120.10]            # 在自定义网络 固定ip,可能需要配合自定义网络
[--network bridge]               # --network 指定所适用的网路模型 默认使用docker0 的 bridge
[--link]                         # --link 创建一条dns记录 可以通过容器名进行容器的ip访问 不推荐
[-p port1:port2]                 # -p 指定端口 port1 宿主主机端口  port2 容器端口
[-e | --env <key>=<value>]       # 参数设置 如:mysql密码
[--privileged]                   # 拥有真正的root权限
[--restart]                      # 重启策略,[no | on-failure | on-failure:3 | always | unless-stopped] -d 时才能使用
<image name | image id>          # 使用的镜像名

docker run -d --name xxx --privileged xxx

# CONTAINER ID  IMAGE       NAMES    COMMAND   CREATED    STATUS         PORTS
# 容器ID         用的那个镜像  容器名称   启动命令    创建时间    状态 up 启动中   端口映射

# 列出所有的容器 
docker ps [-a]       # -a 列出所有的,存活的,运行完毕的
# 列出所有的容器 及 其启动命令
docker ps -a --no-trunc

docker start $(docker ps -aq)                  # 批量启动容器
docker stop <container name>                   # 容器停止
docker rm -f <container name>                  # 删除容器
docker restart <container name>                # 容器重启

docker container inspect  <container name>     # 查看容器信息
3.4.2 容器命令执行
# 进入容器的cli界面 因为容器只会安装必要的命令包 所以不同镜像run的容器具有的命令是不一样的 
# -it 即 -i -t 用来做cmd 交互的
docker exec -it <container name | id> /bin/bash
docker exec -it <container name | id> bash
docker exec -it <container name | id> sh    # 这个界面有点挫

# 直接执行命令
docker exec -it <container name | id> <command>
docker exec -i mysql mysql -uroot -p'root@123' -e "INSERT INTO cti.load_balancer( group_id, dst_uri, resources) VALUES ( 2, 'sip:192.168.1.228:8061', 'channel=100;asr=100;');"

yum install -y vim    # 进入容器中可以安装个vim
3.4.3 查看日志
docker logs [OPTIONS] <container name | id>  # 查看容器日志信息 输出的是 stdout 的内容
-f : 跟踪日志输出
--since :显示某个开始时间的所有日志
-t : 显示时间戳
--tail :仅列出最新N条容器日志

* 日志文件存储位置
/var/lib/docker/containers/容器ID/容器ID-json.log

./log.sh grg-admin | xargs tail -f

docker log相关

3.4.4 大小监控
docker network ls              # 查看网路模型 docker是bridge的
docker top <containerId>       # CPU使用率 内存
docker stats <containerId>     # CPU使用率 内存 常见

weavescope # 一个监控插件
3.4.5 数据持久化
# volume 在 Dockerfile 中可以指定
# volume 在 容器创建时 run 的 -v 指定
# 默认位于 /var/lib/docker/volumes

docker volume ls                        # 查看volume
docker volume inspect <vol name>        # 查看指定volume信息
docker volume create --name <vol name>  # 创建一个volume 默认会挂载一个目录
docker volume rm <vol name>             # 删除一个volume

-v ~/cheng/xx:/var/xx
# -v ~/cheng/xx:/var/xx:ro  指定为readonly
# :ro readonly docker容器中不可以修改
# :z 选项指示绑定安装内容在多个容器之间共享
# :Z 选项表示绑定安装内容是私有的且未共享
# 挂载行为
# 文件夹挂载
1. 若文件夹不存在,则先创建出文件夹(若为多层文件夹,则递归创建)
2. 用host上的文件夹内容覆盖container中的文件夹内容, 无论container中的文件夹是否存在(不存在创建)
注:若host文件夹为空,则会把container中的文件夹覆盖为空
# 文件挂载
1. 文件必须存在,禁止用主机上不存在的文件挂载到container中已经存在的文件
2. 其它行为与文件夹一致
docker run --name mysql01 -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7

解析:
--name mysql01                                #对容器的命名
-d                                            #后台运行
-p 3310:3306                                  #对外暴露端口号3310
-v /home/mysql/conf:/etc/mysql/conf.d         #配置文件挂载到当前宿主机的/home/mysql/conf
-v /home/mysql/data:/var/lib/mysql            #数据挂载到当前宿主机的 /home/mysql/data
-e MYSQL_ROOT_PASSWORD=123456    #设置mysql的root用户的密码是:·123456
3.4.6 文件交互
# 从宿主复制文件到Docker容器
docker cp pkslow/pkslow.txt <containerId>:/opt/h2-data
# 从宿主复制目录到Docker容器
docker cp pkslow <containerId>:/opt/h2-data

# 从容器复制文件或目录到宿主机器
docker cp <containerId>:/opt/h2-data/pkslow ./
docker cp <containerId>:/opt/h2-data/pkslow/pkslow.txt ./
3.4.7 其它
3.4.7.1 Docker 命令修改
# Docker 命令修改
docker container update --restart=always 容器名字
3.4.7.2 容器内 vim 安装
# 容器内 vim 安装
apt-get update &&  apt-get install vim 

若遇到下面问题: error: http://repo.mysql.com/apt/debian buster InRelease: The following signatures couldn’t be verified because the public key is not available: NO_PUBKEY 467B942D3A79BD29

在这里插入图片描述

执行命令
$ apt-key adv --keyserver keyserver.ubuntu.com --recv-keys [根据错误提示的 key 来写这个]
然后再次执行安装即可
3.4.7.3 容器中文乱码
# 容器中文乱码
locale -a    # 查看容器具有哪些语言包
# C
# C.UTF-8
# POSIX    默认使用的

# 可以临时设置为utf-8
export  LANG=C.UTF-8     

# 永久修改
ENV LANG C.UTF-8   # 需要在dockerfile中添加 做成镜像
-eLANG=C.UTF-8     # 创建容器时设置
3.4.7.4 启动容器自启
docker update elasticsearch --restart=always   # 启动容器自启
# 修改无法启动的容器中的内容
1) 重新启动一个新的容器
2) 所有的容器数据都存在/var/lib/docker/路径下, 根据容器id找到文件夹,在里面找配置 使用find命令去寻找
3.4.7.5 容器清理和磁盘查看
# 清理没有使用的数据,包括镜像数据,已经停止的容器
# docker 自动清理空间
$ docker system prune
WARNING! This will remove:
        - all stopped containers                          # 清理停止的容器
        - all networks not used by at least one container # 清理没有使用的网络
        - all dangling images                             # 清理废弃的镜像
        - all build cache                                 # 清理构建缓存
tips: 我们不能在生产环境中运行prune -a命令,因为一些备用镜像(用于备份,回滚等)有时候需要用到,如果这些镜像被删除了,则运行容器时需要重新下载。

# 提供Docker整体磁盘使用率的概况,包括镜像、容器和(本地)volume。所以我们现在随时都可以查看Docker使用了多少资源。
$ docker system df

# 缩写 docker info 的信息
$ docker system info 

3.5 网路

3.5.1 网路模型
  • Host: 容器不会虚拟出自己的网卡,配置主机的IP等,而是使用宿主机的IP和端口
  • Container: 创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP,端口范围
  • None: 该模式关闭了容器的网络功能。
  • Bridge: 默认为该模式,此模式会为每一个容器分配,设置IP等,并将容器连接到一个docker0 的虚拟网桥,通过docker 0 网桥以及iptables nat 表配置与宿主机通信。
  • 自定义网络

在安装Docker 时,它会自动创建三个网络:bridge(创建容器默认连接到此网络),none,host

docker inspect <continerName>     # 查看容器网路信息

# 当安装docker时 就会默认创建一个 docker0 网卡,用于和容器进行通信
docker network ls                         # 查看docker下的网路模型
docker network create <netname>           # 添加一个网路模型
docker network create --subnet=<xxx.xx.xx.xx/xx> <netname>  # 指定网段和网路模型名创建
docker network delete|rm <netname>           # 删除一个网路模型
docker network inspect <netname>          # 查看bridge网路 

# 创建网络
docker network create --driver=bridge --gateway=172.44.0.1 --subnet=172.44.0.0/16 nacoscluster

# 将容器链接到指定的网络中 一个容器可以指定多个网络
docker network connect <network name> <containerName>     

# docker 默认是链接的docker0
# 推荐自定义网路进行连接 启动容器时会自动创建一条dns记录 从而可以通过容器名进行访问
# 使用docker run 创建 Docker 容器时,可以用 --net 或 --network 选项指定容器的网络模式
# 网络信息
[
    {
        "Name": "chat",
        "Id": "52159600637c2b93b2523bc952d39cd648a2d5c9ce4716cba8c5eae5a5ea8a7e",
        "Created": "2021-07-15T15:08:58.251361592+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]
3.5.2 网路命名空间

3.5.2 外部映射
# 端口映射
-p 9090:8080
# 访问宿主机的9090端口 即相当于访问了容器的8080
3.5.2 多机器

3.6 容器启动案例

3.6.1 minio 启动
docker run -p 9000:9000 -p 9001:9001 --name minio-server --privileged=true \
-e "MINIO_ROOT_USER=minio" \
-e "MINIO_ROOT_PASSWORD=minio123" \
-v /home/minio/data:/data \
-v /home/minio/config:/root/.minio \
-d minio/minio server /data --console-address ":9001"

docker run           # docker 启动容器命令
-d                   # 后台启动
-p                   # 端口映射
-name                # 为这个容器取一个名字
-e                   # 设置环境变量
-v                   # 文件挂载位置
minio/minio 
# 传递给了 cmd 将其覆盖
# minio启动命令 (minio/minio 是镜像名字、/data:数据存储位置)
# 选择静态端口号,需要注意下控制台端口号不能和静态端口号一样
server /data --console-address ":9090"     

4. Dockerfile

Image 是根据 dockerfile 的配置来生成镜像的。

官网镜像的DockerFlle查看

4.1 Dockerfile 语法

构建镜像的配置文件 Dockerfile, 没有文件后缀

在这里插入图片描述

#

Dockerfile 中的注解

FROM

指定基础镜像,必须为第一个命令

# 官网镜像地址 https://hub.docker.com/
格式:
  FROM <image> [AS <name>]
  FROM <image>:<tag> [AS <name>]
  FROM <image>@<digest> [AS <name>]
示例: 
   FROM ubuntu:14.04
   FROM debian:buster-slim 
   FROM mysql:5.6
   FROM openjdk:8
注:  
   tag或digest是可选的,如果不使用这两个值时,会使用latest版本的基础镜像,找不到tag会返回错误
   ARG 是唯一可以用在第一个 FROM 前的指令
   FROM 可以多次使用,代表多段构建,FROM 会情况前一次构建的所以状态
   FROM xx AS name, name 可用于下次构建的 FROM 或者 COPY  --from=<name|index> 用于引用此段构造镜像
MAINTAINER

维护者信息

格式:
   MAINTAINER <name>
示例: 
   MAINTAINER xiaoming
LABEL

用于为镜像添加元数据

格式:
   LABEL <key>=<value> <key>=<value> <key>=<value> ...
示例:
  LABEL name="dockerfile-demo" version="1.0"  author="xiaoming"
注:
  使用LABEL指定元数据时,一条LABEL指定可以指定一或多条元数据,指定多条元数据时不同元数据之间通过空格分隔。推荐将所有的元数据通过一条LABEL指令指定,以免生成过多的中间镜像。
RUN

用于指定 docker build 过程中要运行的命令。通常用于安装软件包。

格式:
   shell执行
      RUN <command>
   exec执行
      RUN ["executable", "param1", "param2"]
示例: 
   RUN apk update 
   RUN groupadd -r mysql && useradd -r -g mysql mysql
   RUN ["java", "-jar", "spring-1.0-SNAPSHOT.jar"]
注:  
   RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache
ADD

将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget

格式:
   ADD <src>... <dest>
   ADD ["<src>",... "<dest>"] # 用于支持包含空格的路径
示例: 
   ADD hom* /mydir/           # 添加所有以"hom"开头的文件
   ADD hom?.txt /mydir/       # ? 替代一个单字符,例如:"home.txt"
   ADD test relativeDir/      # 添加 "test" 到 `WORKDIR`/relativeDir/
   ADD test /absoluteDir/     # 添加 "test" 到 /absoluteDir/
   ADD application.yml /etc/itcrazy2016
注:  
   tag或digest是可选的,如果不使用这两个值时,会使用latest版本的基础镜像
COPY

功能类似ADD,但是是不会自动解压文件,也不能访问网络资源

示例: 
   COPY docker-entrypoint.sh /usr/local/bin/
   COPY --from=<前一个阶段> xxx              # 引用前一个阶段的镜像, 进行copy     
   COPY ./grg_chat.sql /docker-entrypoint-initdb.d
CMD

用于指定 docker run 过程中要运行的命令。充当默认命令的角色。

格式:
   CMD ["executable","param1","param2"]    # 执行可执行文件,优先
   CMD command param1 param2               # 执行shell内部命令  
   CMD ["param1","param2"]                 # 设置了ENTRYPOINT时 作为默认参数传递给 ENTRYPOINT

示例: 
   CMD echo "This is a test." | wc -
   CMD ["/usr/bin/wc","--help"]
注:
   CMD主要用于执行容器启动运行时需要执行的程序
   CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。
   CMD执行的命令会被docker run时指定的命令覆盖掉(cmd 充当默认值角色)
   如果 dockerfile 中如果存在多个CMD指令,仅最后一个生效;
docker run -d --name xx  tomcat cmd1 cmd2...   # 最后面跟的 cmd1 cmd2等 将替换Dockerfile 里面的cmd 信息
ENTRYPOINT

用于指定 docker run 过程中要运行的命令。容器正统入口。

格式:
   ENTRYPOINT ["executable", "param1", "param2"]   # 可执行文件, 优先
   ENTRYPOINT command param1 param2                # shell内部命令
示例: 
   ENTRYPOINT ["top", "-b"]
   ENTRYPOINT ["docker-entrypoint.sh"]
注:  
   ENTRYPOINT与CMD非常类似,不同的是通过docker run执行的命令不会覆盖ENTRYPOINT,当运行 docker run 时使用了 --entrypoint 选项,此选项的参数可当作要运行的程序覆盖 ENTRYPOINT 指令指定的程序
   而docker run命令中指定的任何参数,都会被当做参数再次传递给ENTRYPOINT。Dockerfile中只允许有一个ENTRYPOINT命令,多指定时会覆盖前面的设置,而只执行最后的ENTRYPOINT指令。
   CMD 配合作为动态参数
...
ENTRYPOINT ["/bin/echo", "hello"] CMD ["world"]
...

docker run -it              # 运行的容器后无任何参数
输出: hello world

docker run -it myworld      # 运行的容器后跟了 myworld 参数
输出: hello myworld
ENV

设置环境变量

格式:
   ENV <key> <value>   
   #<key>之后的所有内容均会被视为其<value>的组成部分,因此,一次只能设置一个变量
   #可以设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<key>中包含空格,可以使用\来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行
   ENV <key>=<value> ...  
示例:
   ENV MYSQL_MAJOR 5.7
   ENV myName John Doe
   ENV myDog Rex The Dog
   ENV myCat=fluffy
   
内嵌的变量:
HOME,用户主目录
HOSTNAME,默认容器的主机名
PATH,
TERM,默认xterm

* 容器运行时可以根据 -e 或 --env 进行变量赋值  
* 容器启动后在容器中可以通过 env 查看变量
EXPOSE

指定于外界交互的端口

格式:
   EXPOSE <port> [<port>...]
示例:
   EXPOSE 80 443
   EXPOSE 8080
   EXPOSE 11211/tcp 11211/udp
注:
  EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口
VOLUME

用于指定持久化目录

格式:
   VOLUME ["/path/to/dir"]
示例:
   VOLUME /var/lib/mysql
   VOLUME ["/data"]
   VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
注:
   一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:
# 1. 卷可以容器间共享和重用
# 2. 容器并不一定要和其它容器共享卷
# 3. 修改卷后会立即生效
# 4. 对卷的修改不会对镜像产生影响
# 5. 卷会一直存在,直到没有任何容器在使用它
WORKDIR

工作目录,类似于cd命令

格式:
   WORKDIR /path/to/workdir                   # 不存在则创建
示例:
   # 多个 WORKDIR 提供了相对路径 会相对于之前的进行创建
   WORKDIR /a     # 这时工作目录为/a
   WORKDIR b      # 这时工作目录为/a/b
   WORKDIR c      # 这时工作目录为/a/b/c
注:
   WORKDIR 指定,登录命令行界面后会直接到达WORKDIR指定的目录
   WORKDIR 可以解析之前由ENV设置的环境变量
   通过WORKDIR设置容器的工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都会在该目录下执行。
  在使用docker run运行容器时,也是在该指定的目录下执行的,可以通过-w <path> 参数覆盖构建时所设置的工作目录, 使用新指定的目录。
USER

指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户。使用USER指定用户时,可以使用用户名、UID或GID,或是两者的组合。当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户

格式:
   USER user
   USER user:group
   USER uid
   USER uid:gid
   USER user:gid
   USER uid:group
示例:
   USER www
注:
   使用USER指定用户后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT都将使用该用户。镜像构建完成后,通过docker run运行容器时,可以通过-u参数来覆盖所指定的用户。
ARG

用于指定传递给构建运行时的变量

格式:
   ARG <name>[=<default value>]
示例:
   ARG site
   ARG build_user=www
描述
   ARG 是唯一可以用在第一个 FROM 前的指令
   
   在docker build时以--build-arg site=site_value 的方式赋值, 若改变了被使用且未赋值,则build失败
   [Warning] One or more build-args [foo] were not consumed.
   
   容器启动后无效

docker自带的arg参数:
HTTP_PROXY
http_proxy
HTTPS_PROXY
https_proxy
FTP_PROXY
ftp_proxy
NO_PROXY
no_proxy

https://www.cnblogs.com/jiangbo44/p/14117328.html
https://www.cnblogs.com/jiangbo44/p/14117341.html
ONBUILD

用于设置镜像触发器

格式:
   ONBUILD [INSTRUCTION]
示例:
   ONBUILD ADD . /app/src
   ONBUILD RUN /usr/local/bin/python-build --dir /app/src
注:
   当所构建的镜像被用做其它镜像的基础镜像,该镜像中的触发器将会被钥触发

4.2 文件案例

4.2.1 SpringBoot镜像
(1)创建一个Spring Boot项目
(2)写一个controller
  @RestController
  public class DockerController {
    @GetMapping("/dockerfile")
    @ResponseBody
    String dockerfile() {
      return "hello docker" ;
   }
 }
(3)mvn clean package打成一个jar包
在target下找到"dockerfile-demo-0.0.1-SNAPSHOT.jar"
 
(4)在docker环境中新建一个目录"first-dockerfile"
 
(5)上传"dockerfile-demo-0.0.1-SNAPSHOT.jar"到该目录下,并且在此目录创建Dockerfile
(6)创建Dockerfile文件,编写内容
FROM openjdk:8
MAINTAINER chenglei
COPY spring-1.0-SNAPSHOT.jar spring-1.0-SNAPSHOT.jar
CMD ["java","-jar","spring-1.0-SNAPSHOT.jar"]
 
(7)基于Dockerfile构建镜像
docker build -t test-docker-image .
(8)基于image创建container
docker run -d --name user01 -p 6666:8080 test-docker-image
(9)查看启动日志docker logs user01
(10)宿主机上访问
curl localhost:6666/dockerfile
hello docker
(11)还可以再次启动一个
docker run -d --name user02 -p 8081:8080 test-docker-image
4.2.2 SpringBoot分层镜像
# 第一阶段
FROM openjdk:8 as builder
# 工作目录为/build 相对目录  
WORKDIR /build
# 设置常量
ARG JAR_FILE=target/pig-register.jar
# 拷贝target/pig-register.jar  到/build/app.jar
COPY ${JAR_FILE} app.jar
# 执行shell命令 使用分层 这里就是解压jar包分层成各个目录  目的是为了更新的时候局部更新 加快镜像pull速度
# /build/dependencies
# /build/snapshot-dependencies
# /build/spring-boot-loader
# /build/application
RUN java -Djarmode=layertools -jar app.jar extract && rm app.jar

# 第二阶段 引用第一阶段的镜像builder
FROM openjdk:8
MAINTAINER grg_video@grgbanking.com
ENV JAVA_OPTS="-Xms128m -Xmx256m -Duser.timezone=GMT+8 -Djava.security.egd=file:/dev/./urandom"
WORKDIR /opt

# 将builder(第一阶段)的文件copy到/opt
COPY --from=builder /build/dependencies/ ./
COPY --from=builder /build/snapshot-dependencies/ ./
COPY --from=builder /build/spring-boot-loader/ ./
COPY --from=builder /build/application/ ./

EXPOSE 8848

# 容器启动时执行
CMD java $JAVA_OPTS org.springframework.boot.loader.JarLauncher
# war 包
...
ARG JAR_FILE=target/grg-media.war
COPY ${JAR_FILE} app.war
RUN java -Djarmode=layertools -jar app.war extract && rm app.war
...
CMD java $JAVA_OPTS org.springframework.boot.loader.WarLauncher
4.2.3 常用镜像使用收集
# JDK
FROM openjdk:8
FROM openjdk:8-jdk-alpine

# MySql
FROM mysql:5.6
4.2.4 Mysql 镜像
# 启动的时候,设置环境变量就可以配置 mysql的密码
# MYSQL_ROOT_PASSWORD :root的密码
# MYSQL_USER :建一个普通用户
# MYSQL_PASSWORD :普通用户的密码

docker run --name mysql01 -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7

# 当需要修改mysql密码的时候,发现修改环境变量再重启,密码并没有修改,因为已经持久化了,密码存下来了,不会再读取环境变量了。只能通过mysql命令行来修改了

# 修改普通用户,只改一个就好
SET PASSWORD FOR 'youruser' = PASSWORD('xxxxxxxx');

# 修改root用户,改两个
SET PASSWORD FOR 'root' = PASSWORD('xxxxxxxx');               # 修改此 发现remote 可以连接,但是docker start container 启动不了
SET PASSWORD FOR 'root'@'localhost'=PASSWORD('xxxxxxxx');     # 修改此 用于docker 自身mysql启动

# mysql 容器 数据初始化
# mysql 镜像在容器启动时自动执行 /docker-entrypoint-initdb.d 目录下的shell和sql 脚本,所以把sql脚本放入改目录下,即可完成创建容器时初始化数据库
COPY ./grg_chat.sql /docker-entrypoint-initdb.d
4.2.5 Nginx安装
docker run -d --name nginx \
-v /home/chenglei/note:/usr/share/nginx/html/note \
-v /home/chenglei/nginx/nginx.conf:/etc/nginx/nginx.conf:ro \
-v /home/chenglei/nginx/conf.d:/etc/nginx/conf.d \
-v /home/chenglei/nginx/logs:/var/log/nginx/ \
-p80:80 --privileged nginx

# 挂载的目录文件需要提前创建好
# 1. 挂载项目地址
# 2. 挂载配置文件
# 3. 挂载子配置文件
# 4. 挂载日志
4.2.6 Docker Postgre安装
docker run -it -d --name postgresql -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=lei.cheng -p 15432:5432 -v /home/gs/postgres/data:/var/lib/postgresql postgres:12.3

5. 网络

5.1 网络模型

在这里插入图片描述

5.2 网络通信

计算机通信,网卡是计算机通信的硬件支撑,唯一的MAC地址。

在这里插入图片描述

5.3 网卡

默认本地网卡
# 查看网卡的信息
ip link show
ip a
ls /sys/class/net

# 网卡配置文件目录 可以对网卡进行配置的修改 网卡即是文件
/etc/sysconfig/network-scripts/

# 网卡解读
状态: UP / DOWN / UNKOWN
link/ether: MAC地址
inet: 绑定的Ip地址

ip addr add 192.168.0.100/24 dev eth0        # 给网卡添加IP地址
ip addr delete 192.168.0.100/24 dev eth0     # 给网卡删除IP地址
service network restart / systemctl restart network     # 重启网卡
ifup/ifdown eth0                             # 启动关闭指定网卡 
ip link set eth0 up/down                     # 启动关闭指定网卡 
网卡隔离

​ network namespace, docker的底层实现就是通过namespace实现的,所以网卡也是可以通过命名空间进行隔离的。

​ 不同的 network namespace 是相互隔离的。

命令
ip netns list          # 查看隔离的网卡
ip netns add ns1       # 生成一个隔离的网卡
ip netns delete ns1    # 删除一个隔离的网卡
ip netns exec <network name> <command>   # 命名空间网卡执行网卡相关命令
ip link add <name1> type veth peer name <name2>    # 生成互通的网卡信息

# 添加网卡信息到命名空间中的网卡中
ip link set <network name> netns <networknamespace network name>

注: 当创建一个网卡时,会默认有个IO的网卡,该网卡为回环地址,本地网卡也是有的**

案例
1. ip netns add net1           # 添加一个隔离网卡
2. ip netns exec net1 ip a     # 查看添加的隔离网卡信息 会发现 lo 网卡
3. ip netns exec net1 ifup lo  # 启动回环网卡 lo
4. ip netns exec net1 ip a     # 再次查看
5. 以相同的步骤 1-4 创建 net2

如何使得两者通信呢?

需要给net1设置一个网卡,给net2设置一个网卡,net1和net2的网卡需要能够通信

veth pair :Virtual Ethernet Pair,是一个成对的端口,可以生成一个成对的网卡,这两个网卡互通

7. ip link add wk-net1 type veth peer name wk-net2   # 生成wk-net1和wk-net2网卡 
8. ip lisk  # 查看生成的两个网卡

9. ip link set wk-net1 netns net1      # 将网卡wk-net1添加到net1  
10. ip link set wk-net2 netns net2    # 将网卡wk-net2添加到net2

11. 查看网卡情况 本地生成的网卡消失 添加到了命名空间中网卡中
ip link
ip netns exec net1 ip a
ip netns exec net2 ip a

12. 给两个网卡添加同一网段的ip
ip netns exec net1 ip addr add 192.168.0.11/24 dev wk-net1
ip netns exec net2 ip addr add 192.168.0.12/24 dev wk-net2

13. 查看网卡情况 ip 添加ok
ip link
ip netns exec net1 ip a
ip netns exec net2 ip a

14. 启动两个网卡 状态为 UP
ip netns exec net1 ip link set wk-net1 up
ip netns exec net2 ip link set wk-net2 up

15. ping 成功
ip netns exec net1 ping 192.168.0.12
ip netns exec net2 ping 192.168.0.11

在这里插入图片描述

Docker网卡

​ 可以知道docker是bridge模式,假如启动tomcat01和tomcat02容器, tomcat01会和docker0(安装docker时会自动安装docker0网卡)有成对的网卡(veth pair)互通,tomcat02和docker0有成对的网卡互通,那么tomcat01即可以链接tomcat02。其它的都会和docker0互通。

在这里插入图片描述

可以查看docker默认就是bridge模式

docker network ls                 # docker的网络模型
docker network inspect bridge     # docker bridge 中的信息

Birdge: 默认,单机vm容器互联

Host: 使用vm的网卡, 即容器就是该vm, 容易冲突

None: 没啥用

6. 持久化

可以说docker是通过 volume 来进行容器文件和宿主机文件共享的。

  • 当容器删除时,宿主机文件仍存在,所以这是一种持久化,也可以根据文件对容器数据进行恢复。
  • 因为共享,当宿主机文件内容等发生变化,也会反馈到容器中。可以用来动态变更,部署。
# volume 在 Dockerfile 中可以指定
# volume 在 容器创建时 run 的 -v 指定

docker volume ls                        # 查看volume
docker volume inspect <vol name>        # 查看指定volume信息
docker volume create --name <vol name>  # 创建一个volume 默认会挂载一个目录
docker volume rm <vol name>             # 删除一个volume

已启动的docker容器挂载新路径

# 停止 docker 容器
systemctl stop docker

# 进入要修改的容器中
cd /var/lib/docker/containers/93531fb93b4fe225251947ee4c9f1a4b72ab707a9bb45118dd464add0e9bc790

# 编辑 
vim hostconfig.json

7. docker compose

​ 用于定义和运行多容器 Docker 的应用程序工具,用于单机一键式部署。Docker-Compose将所管理的容器分为三层,分别是工程(project),服务(service)以及容器(container)。

7.1 安装

win all 和mac 环境安装docker会默认安装docker compose, linux 需要再次安装。

官网:https://docs.docker.com/compose/ 阿里文章

# docker 19 版本
sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
或者
sudo curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

sudo chmod +x /usr/local/bin/docker-compose

docker-compose --version
# docker 20 版本
sudo curl -L "https://github.com/docker/compose/releases/download/1.26.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 可以不执行
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

7.2 常用命令

  • Docker-compose 命令格式

    docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]
    
    -f --file FILE指定Compose模板文件,默认为docker-compose.yml
    -p --project-name NAME 指定项目名称,默认使用当前所在目录为项目名
    --verbose  输出更多调试信息
    -v,-version 打印版本并退出
    --log-level LEVEL 定义日志等级(DEBUG, INFO, WARNING, ERROR, CRITICAL)
    
  • docker-compose up

    该命令可以自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作。

    docker-compose -f xxxx.yml up -d
    
    docker-compose up [options] [--scale SERVICE=NUM...] [SERVICE...]
    选项包括:
    -d 在后台运行服务容器
    -no-color 不是有颜色来区分不同的服务的控制输出
    -no-deps 不启动服务所链接的容器
    --force-recreate 强制重新创建容器,不能与-no-recreate同时使用
    –no-recreate 如果容器已经存在,则不重新创建,不能与–force-recreate同时使用
    –no-build 不自动构建缺失的服务镜像
    –build 在启动容器前构建服务镜像
    –abort-on-container-exit 停止所有容器,如果任何一个容器被停止,不能与-d同时使用
    -t, –timeout TIMEOUT 停止容器时候的超时(默认为10秒)
    –remove-orphans 删除服务中没有在compose文件中定义的容器
    
  • docker-compose ps

    docker-compose  ps [options] [SERVICE...]
    列出项目(docker-compose.yml)中所有的容器状态信息
    
  • docker-compose stop

    docker-compose stop [options] [SERVICE...]
    选项包括
    -t, –timeout TIMEOUT 停止容器时候的超时(默认为10秒)
    docker-compose stop
    停止正在运行的容器,可以通过docker-compose start 再次启动
    
  • docker-compose -h

    docker-compose -h
    查看帮助
    
  • docker-compose down

    docker-compose down [options]
    停止和删除容器、网络、卷、镜像。
    选项包括:
    –rmi type,删除镜像,类型必须是:all,删除compose文件中定义的所有镜像;local,删除镜像名为空的镜像
    -v, –volumes,删除已经在compose文件中定义的和匿名的附在容器上的数据卷
    –remove-orphans,删除服务中没有在compose中定义的容器
    docker-compose down
    停用移除所有容器以及网络相关
    
  • docker-compose logs

    docker-compose logs [options] [SERVICE...]
    查看服务容器的输出。默认情况下,docker-compose将对不同的服务输出使用不同的颜色来区分。可以通过–no-color来关闭颜色。
    docker-compose logs
    查看服务容器的输出
    -f 跟踪日志输出
    
  • docker-compose bulid

    docker-compose build [options] [--build-arg key=val...] [SERVICE...]
    构建(重新构建)项目中的服务容器。
    选项包括:
    –compress 通过gzip压缩构建上下环境
    –force-rm 删除构建过程中的临时容器
    –no-cache 构建镜像过程中不使用缓存
    –pull 始终尝试通过拉取操作来获取更新版本的镜像
    -m, –memory MEM为构建的容器设置内存大小
    –build-arg key=val为服务设置build-time变量
    服务容器一旦构建后,将会带上一个标记名。可以随时在项目目录下运行docker-compose build来重新构建服务
    
  • docker-compose pull

    docker-compose pull [options] [SERVICE...]
    拉取服务依赖的镜像。
    选项包括:
    –ignore-pull-failures,忽略拉取镜像过程中的错误
    –parallel,多个镜像同时拉取
    –quiet,拉取镜像过程中不打印进度信息
    docker-compose pull
    拉取服务依赖的镜像
    
  • docker-compose restart

    docker-compose restart [options] [SERVICE...]
    重启项目中的服务。
    选项包括:
    -t, –timeout TIMEOUT,指定重启前停止容器的超时(默认为10秒)
    docker-compose restart
    重启项目中的服务
    
  • docker-compose rm

    docker-compose rm [options] [SERVICE...]
    删除所有(停止状态的)服务容器。
    选项包括:
    –f, –force,强制直接删除,包括非停止状态的容器
    -v,删除容器所挂载的数据卷
    docker-compose rm
    删除所有(停止状态的)服务容器。推荐先执行docker-compose stop命令来停止容器。
    
  • docker-compose start

    docker-compose start [SERVICE...]
    docker-compose start
    启动已经存在的服务容器。
    
  • docker-compose run

    docker-compose run [options] [-v VOLUME...] [-p PORT...] [-e KEY=VAL...] SERVICE [COMMAND] [ARGS...]
    在指定服务上执行一个命令。
    docker-compose run ubuntu ping www.baidu.com
    在指定容器上执行一个ping命令。
    
  • docker-compose scale

    docker-compose scale web=3 db=2
    设置指定服务运行的容器个数。通过service=num的参数来设置数量
    
  • docker-compose pause

    docker-compose pause [SERVICE...]
    暂停一个服务容器
    
  • docker-compose kill

    docker-compose kill [options] [SERVICE...]
    通过发送SIGKILL信号来强制停止服务容器。
    支持通过-s参数来指定发送的信号,例如通过如下指令发送SIGINT信号:
    docker-compose kill -s SIGINT
    
  • docker-compose config

    docker-compose config [options]
    验证并查看compose文件配置。
    选项包括:
    –resolve-image-digests 将镜像标签标记为摘要
    -q, –quiet 只验证配置,不输出。 当配置正确时,不输出任何内容,当文件配置错误,输出错误信息
    –services 打印服务名,一行一个
    –volumes 打印数据卷名,一行一个
    
  • docker-compose create

    docker-compose create [options] [SERVICE...]
    为服务创建容器。
    选项包括:
    –force-recreate:重新创建容器,即使配置和镜像没有改变,不兼容–no-recreate参数
    –no-recreate:如果容器已经存在,不需要重新创建,不兼容–force-recreate参数
    –no-build:不创建镜像,即使缺失
    –build:创建容器前  ,生成镜像
    
  • docker-compose exec

    docker-compose exec [options] SERVICE COMMAND [ARGS...]
    选项包括:
    -d 分离模式,后台运行命令。
    –privileged 获取特权。
    –user USER 指定运行的用户。
    -T 禁用分配TTY,默认docker-compose exec分配TTY。
    –index=index,当一个服务拥有多个容器时,可通过该参数登陆到该服务下的任何服务,例如:docker-compose exec –index=1 web /bin/bash ,web服务中包含多个容器
    
  • docker-compose port

    docker-compose port [options] SERVICE PRIVATE_PORT
    显示某个容器端口所映射的公共端口。
    选项包括:
    –protocol=proto,指定端口协议,TCP(默认值)或者UDP
    –index=index,如果同意服务存在多个容器,指定命令对象容器的序号(默认为1)
    
  • docker-compose push

    docker-compose push [options] [SERVICE...]
    推送服务依的镜像。
    选项包括:
    –ignore-push-failures 忽略推送镜像过程中的错误
    
  • docker-compose uppause

    docker-compose unpause [SERVICE...]
    恢复处于暂停状态中的服务。
    

7.3 模板配置

7.3.1 Docker-compose模板文件简介

​ Compose允许用户通过一个docker-compose.yml模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)。
​ Compose模板文件是一个定义服务、网络和卷的YAML文件。Compose模板文件默认路径是当前目录下的docker-compose.yml,可以使用.yml或.yaml作为文件扩展名。Docker-Compose标准模板文件应该包含version、services、networks 三大部分,最关键的是services和networks两个部分。

# Compose目前有三个版本分别为Version 1,Version 2,Version 3,Compose区分Version 1和Version 2(Compose 1.6.0+,Docker Engine 1.10.0+)。Version 2支持更多的指令。Version 1将来会被弃用。
version: '2'
# Docker-Compose标准模板文件应该包含version、services、networks 三大部分
services:
  log:                                 # 构建的模块名
    image: vmware/harbor-log:v1.5.1    # 使用的镜像 没有的话会去pull
    container_name: harbor-log         # 将要创建的容器名称
    restart: always                    # docker 重启时 容器也重新启动
    volumes: 
      - /var/log/harbor/:/var/log/docker/:z
      - ./common/config/log/:/etc/logrotate.d/:z
    ports:
      - 127.0.0.1:1514:10514
    networks:
      - harbor
  registry:
    image: vmware/registry-photon:v2.6.2-v1.5.1
    container_name: harbor-registry
    restart: always
    volumes:
      - /data/registry:/storage:z
      - ./common/config/registry/:/etc/registry/:z
    networks:
      - harbor
    environment:                         # 设置环境变量 用于传递给容器
      - GODEBUG=netdns=cgo
    command:
      ["serve", "/etc/registry/config.yml"]
    depends_on:
      - log
    logging:
      driver: "syslog"
      options:
        syslog-address: "tcp://127.0.0.1:1514"
        tag: "registry"
  mysql:
    image: vmware/harbor-db:v1.5.1
    container_name: harbor-db
    restart: always
    volumes:
      - /data/database:/var/lib/mysql:z
    networks:
      - harbor
    env_file:
      - ./common/config/db/env
    depends_on:
      - log
    logging:
      driver: "syslog"
      options:
        syslog-address: "tcp://127.0.0.1:1514"
        tag: "mysql"
  adminserver:
    image: vmware/harbor-adminserver:v1.5.1
    container_name: harbor-adminserver
    env_file:
      - ./common/config/adminserver/env
    restart: always
    volumes:
      - /data/config/:/etc/adminserver/config/:z
      - /data/secretkey:/etc/adminserver/key:z
      - /data/:/data/:z
    networks:
      - harbor
    depends_on:
      - log
    logging:
      driver: "syslog"
      options:
        syslog-address: "tcp://127.0.0.1:1514"
        tag: "adminserver"
  ui:
    image: vmware/harbor-ui:v1.5.1
    container_name: harbor-ui
    env_file:
      - ./common/config/ui/env
    restart: always
    volumes:
      - ./common/config/ui/app.conf:/etc/ui/app.conf:z
      - ./common/config/ui/private_key.pem:/etc/ui/private_key.pem:z
      - ./common/config/ui/certificates/:/etc/ui/certificates/:z
      - /data/secretkey:/etc/ui/key:z
      - /data/ca_download/:/etc/ui/ca/:z
      - /data/psc/:/etc/ui/token/:z
    networks:
      - harbor
    depends_on:
      - log
      - adminserver
      - registry
    logging:
      driver: "syslog"
      options:
        syslog-address: "tcp://127.0.0.1:1514"
        tag: "ui"
  jobservice:
    image: vmware/harbor-jobservice:v1.5.1
    container_name: harbor-jobservice
    env_file:
      - ./common/config/jobservice/env
    restart: always
    volumes:
      - /data/job_logs:/var/log/jobs:z
      - ./common/config/jobservice/config.yml:/etc/jobservice/config.yml:z
    networks:
      - harbor
    depends_on:
      - redis
      - ui
      - adminserver
    logging:
      driver: "syslog"
      options:
        syslog-address: "tcp://127.0.0.1:1514"
        tag: "jobservice"
  redis:
    image: vmware/redis-photon:v1.5.1
    container_name: harbor-redis
    restart: always
    volumes:
      - /data/redis:/data
    networks:
      - harbor
    depends_on:
      - log
    logging:
      driver: "syslog"
      options:
        syslog-address: "tcp://127.0.0.1:1514"
        tag: "redis"
  proxy:
    image: vmware/nginx-photon:v1.5.1
    container_name: harbor-nginx
    restart: always
    volumes:
      - ./common/config/nginx:/etc/nginx:z
    networks:
      - harbor
    ports:
      - 8081:80
      - 443:443
      - 4443:4443
    depends_on:
      - mysql
      - registry
      - ui
      - log
    logging:
      driver: "syslog"
      options:
        syslog-address: "tcp://127.0.0.1:1514"
        tag: "proxy"
networks:
  harbor:
    external: false
7.3.2 参数简介

参照文档

参数描述
imageimage是指定服务的镜像名称或镜像ID。如果镜像在本地不存在,Compose将会尝试拉取镜像。
build服务除了可以基于指定的镜像,还可以基于一份Dockerfile,在使用up启动时执行构建任务,构建标签是build,可以指定Dockerfile所在文件夹的路径。Compose将会利用Dockerfile自动构建镜像,然后使用镜像启动服务容器。
contextcontext选项可以是Dockerfile的文件路径,也可以是到链接到git仓库的url,当提供的值是相对路径时,被解析为相对于撰写文件的路径,此目录也是发送到Docker守护进程的context
dockerfile使用dockerfile文件来构建,必须指定构建路径
commond使用command可以覆盖容器启动后默认执行的命令。
container_nameCompose的容器名称格式是:<项目名称><服务名称><序号>
可以自定义项目名称、服务名称,但如果想完全控制容器的命名,可以使用标签指定
depends_on在使用Compose时,最大的好处就是少打启动命令,但一般项目容器启动的顺序是有要求的,如果直接从上到下启动容器,必然会因为容器依赖问题而启动失败。例如在没启动数据库容器的时候启动应用容器,应用容器会因为找不到数据库而退出。depends_on标签用于解决容器的依赖、启动先后的问题
PID将PID模式设置为主机PID模式,跟主机系统共享进程命名空间。容器使用pid标签将能够访问和操纵其他容器和宿主机的名称空间。
portsports用于映射端口的标签。
extra_hosts添加主机名的标签,会在/etc/hosts文件中添加一些记录。
volumes挂载一个目录或者一个已存在的数据卷容器,可以直接使用 [HOST:CONTAINER]格式,或者使用[HOST:CONTAINER:ro]格式,后者对于容器来说,数据卷是只读的,可以有效保护宿主机的文件系统。
volumes_from从另一个服务或容器挂载其数据卷
dns自定义DNS服务器。可以是一个值,也可以是一个列表。
expose暴露端口,但不映射到宿主机,只允许能被连接的服务访问。仅可以指定内部端口为参数
links链接到其它服务中的容器。使用服务名称(同时作为别名),或者“服务名称:服务别名”(如 SERVICE:ALIAS)
net设置网络模式。

配置参数

7.3.3 网络

networks通常应用于集群服务,从而使得不同的应用程序得以在相同的网络中运行,从而解决网络隔离问题。

默认情况容器会被添加到app_default网络中。使用docker network ls可以查看网络列表,docker network inspect <container id>可以查看对应网络的配置。

使用

7.4 案例

7.4.1 配置 Elasticsearch
version: '2'
services:
  elasticsearch:
    container_name: elasticsearch
    image: elasticsearch:7.7.0
    ports:
      - "9200:9200"
    volumes:
      - /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
      - /mydata/elasticsearch/data:/usr/share/elasticsearch/data
      - /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins
    environment:
      - "ES_JAVA_OPTS=-Xms64m -Xmx128m"
      - "discovery.type=single-node"
      - "COMPOSE_PROJECT_NAME=elasticsearch-server"
    restart: always
docker-compose up            # 启动运行
docker-compose up -d         # 后台启动运行
7.4.2 配置一个spring boot 项目
version: '2'
# 声明已存在的网络来使用
networks:
  chenglei_default:
    external: true      
services:
  note_application:
    container_name: note
    build:
      context: ./
      dockerfile: Dockerfile
    image: note_application
    restart: always
    privileged: true
    ports:
    # 不映射到主机端口 只是容器端口
      - "8631"   
    volumes:
      - /home/chenglei/nginx/www/note:/opt/BOOT-INF/classes/note/
      - /home/chenglei/nginx/www/note/image:/opt/BOOT-INF/classes/static/image/
    environment:
      - "LANG=C.UTF-8"
      - "LC_ALL=C.UTF-8"
    networks:
      - "chenglei_default"

8. docker Swarm

将多台安装了docker的机器组成集群,进行管理,对外界提供服务。

9. docker 存储驱动

docker默认的存储目录是 /var/lib/docker

docker info | grep 'Docker Root Dir'

9.1 目录说明

/var/lib/docker/
├── buildkit 
├── containers                       -- 用于存储容器信息,日志文件  
├── image                            -- 用来存储镜像中间件及本身信息,大小,依赖信息
├── network                          -- docker 网络信息
├── overlay2
    ├── xxxxxxxxxxxxxxx              -- 镜像容器存储分层共享
    └── l                            -- 软连接
├── plugins 
├── runtimes 
├── swarm 
├── tmp                              -- docker临时目录
├── trust                            -- docker信任目录
└── volumes                          -- docker卷目录

9.2 overlay2

​ OverlayFS是一种和AUFS很类似的文件系统,Docker的overlay存储驱动利用了很多OverlayFS特性来构建和管理镜像与容器的磁盘结构。所以可以认为OverlayFS代表整个文件系统,而overlay/overlay2表示Docker的存储驱动。

​ 自从Docker1.12起,Docker也支持overlay2存储驱动,相比于overlay来说,overlay2在inode优化上更加高效。但overlay2驱动只兼容Linux kernel4.0以上的版本。

**总结:**overlay2 是用来管理镜像和容器文件存储的驱动。

**底层:**多个容器可以有相同的镜像,所以使用分层共享的方法能够最大的节约资源。

9.2.1 docker 配置

修改/etc/docker/daemon.json如下重启即可,默认overlay地址 var/lib/docker/overlay2

// 原来的
{
  "registry-mirrors": ["https://8fij84na.mirror.aliyuncs.com"]
}
// 可以指定目录
{
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true"
  ]
}
9.2.2 镜像分层与共享

overlay 浅析

overlay2主要由merged、lowerdir、upperdir、workdir组成。

docker inspect 容器iD 可以找到下面目录对应的地址

  • LowerDir

    下层,镜像层就是lowerdir

  • UpperDir

    上层,容器层是upperdir

  • MergedDir

    暴露在外的统一视图就是所谓的merged,其实就是容器本身

  • WorkDir

容器层(upperdir)的文件是显性的,会隐藏镜像层(lowerdir)相同文件的存在。容器映射(merged)显示出统一的视图。

在这里插入图片描述

docker pull xxx 的时候可以观察镜像有多少层,每一层在/var/lib/docker/overlay/下都有自己的目录

l 目录包含了很多软连接,使用短名称指向了其他层。短名称用于避免mount参数时达到页面大小的限制。

查看目录

ls 6a94db61cc096f268cf952cf9cbae86380d813970baea27ef2bfe4a212957c46

目录描述
lowerlower lower文件指出了该层的组成,文件包含了容器的镜像层顶层的ID,符号来分割不同的底层,并且顺序是从高层到底层。
link包含l 目录对应的短名
diff
work
committed

10. 底层原理

11. 扩展知识

11.1 镜像中的 :latest :alpine

:latest 表示最终版本的镜像,即最新版本

:alpine 和 :latest 一样,不过相比latest,alpine有一下的区别

  • alpine镜像用的是Alpine Linux内核,比ubuntu内核要小很多

  • 如要进入alpine容器,命令是(后面的路径不是/bin/bash)

    $ docker exec -it dnmp_nginx_1 /bin/sh
    

注: alpine linux 是 linux 轻量级内核

11.2 查看docker 容器的Id

docker ps -aqf "name=grg-admin"
docker inspect --format="{\{.Id}}"  grg-admin

11.3 查看docker容器的log dirver

# https://zhuanlan.zhihu.com/p/339258388
docker info | grep Logging

11.4 查看对应容器 stdout 日志

docker inspect --format="{\{.LogPath}}" grg-admin | xargs tail -f
docker inspect --format="{\{.Id}}" grg-admin | xargs -I ${CONTAINER_ID} tail -f '/var/lib/docker/containers/'${CONTAINER_ID}'/'${CONTAINER_ID}'-json.log'

11.5 docker.service

docker.service 作为 docker 的启动服务脚本,类似于java jar的启动,通常会做一些启动配置

# 通常的目录地址为
/usr/lib/systemd/system/docker.service

# 常用的操作
# 重载unit配置文件
systemctl daemon-reload
# 启动Docker
systemctl start docker
# 设置开机自启
systemctl enable docker
# 查看Docker状态
systemctl status docker

配置加速器

# 使用 upstart 初始化的系统
在 /etc/default/docker 文件中添加
DOCKER_OPTS="--registry-mirror=https://registry.docker-cn.com"

或者

# 使用 systemd 初始化的系统 如 CentOS7
在 /etc/docker/daemon.json 文件中添加
{
    "registry-mirrors":["https://reg-mirror.qiniu.com/"]
}

以上知道在 daocker 配置 DOCKER_OPTS 参数,完全可以使用 /etc/docker/daemon.json 添加的方式,配置结束后需要重启 docker 才可以。

12. Docker使用中可能遇到的问题

12.1 Mysql 容器启动后

# 创建容器的命令
docker run -d --name pig-mysql -p3306:3306 --network chat -v ~/chenglei/mysql/conf:/etc/mysql/conf.d -v ~/chenglei/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --privileged mysql:5.7.8

# 容器中执行
mysql -uroot -p123456 -h127.0.0.1 -P 3306  # 可以正确进入

# 若出现以下截图问题 就是命令不全

在这里插入图片描述

12.2 jstack 打印栈信息

在docker容器中 jps 发现java的进程号是1,jstack 1 打印出错

在这里插入图片描述

使用openjdk:8-alpine构建的java镜像,使用jstack命令打印线程的时候会提示以上错误。

  • 使用centos+java镜像,可以正常打印线程堆栈,但是这种方式的缺陷就是镜像太大,大约600M左右
  • 使用alpine+java镜像,以/bin/sh方式启动docker,然后手动启动java进程,这时java进程的PID不为1,这种方式能够正常打印线程堆栈,这种方式缺点就是java进程如果异常退出了,docker不会检测到,所以无法做自动重启等操作
  • 使用alpine+java镜像,如果是以直接运行java进程的方式启动docker,也就是说java进程的PID为1,这种方式无法正常打印线程堆栈(可以在做成容器时使用tiny 从而曲线解决)

12.3 运行jmap问题

 Can't attach to the process: ptrace(PTRACE_ATTACH, ..) failed for 6: Operation not permitted

由于docker 自 1.10 版本开始加入的安全特性。 jmap 这类 JDK 工具依赖于 Linux 的 PTRACE_ATTACH,而 Docker 自 1.10 版本开始,默认的 seccomp 配置文件中禁用了 ptrace。

  • 在启动容器即docker run 时

    # 方法一 明确指定
    docker run --cap-add=SYS_PTRACE xxxx
    # 方法二 关闭 seccomp  (或者将ptrace添加到允许的名单中)
    docker run --security-opt seccomp:unconfined 
    
  • docker compose 支持

    services:
      api:
        ...
        cap_add:
          - SYS_PTRACE
    

12.4 nginx 修改停止容器的配置

/var/lib/docker/overlay2/

# 查看容器报错原因
[root@pro nginx]# docker logs nginx
nginx: [emerg] unknown directive "gizp" in /etc/nginx/nginx.conf:29
# 在此目录找到nginx容器的配置文件
[root@pro nginx]# cd /var/lib/docker/overlay2/
[root@pro overlay2]# find ./ -name nginx.conf
./7baeb968df6b073708cce37a182cf54fd033023a5eda6bb6d1077438d950ce6e/diff/etc/nginx/nginx.conf
# 将文件修改正确
[root@pro overlay2]# vim ./7baeb968df6b073708cce37a182cf54fd033023a5eda6bb6d1077438d950ce6e/diff/etc/nginx/nginx.conf
# 重启容器
[root@pro overlay2]# docker restart nginx
nginx

12.5 容器挂载文件时,文件名乱码

指定容器环境使用的编码即可

# 在容器启动时指定环境变量 设置环境的编码
-e LANG=C.UTF-8 
-e LC_ALL=C.UTF-8 

12.6 docker-compose 设置网络

ERROR: Service "note_application" uses an undefined network "chenglei_default"

原因: 因为chenglei_default 存在,但是在docker-compose 中不能直接使用,需要声明使用外部网络才行

# 声明已存在的网络来使用
networks:
  chenglei_default:
    external: true    

12.7 docker 下的数据库备份

#! /bin/bash

DATE=`date +%Y%m%d%H%M%S`
BACK_DATA=erp-${DATE}.sql
#导出表结构,不包括表数据
#docker exec -i xin-mysql-pro mysqldump -d erp-dq-pro -u root -p123456  --tables sys_user > /data/mysql/data/backup/${BACK_DATA}
#导出表数据,xin-mysql为数据库名
#docker exec -i xin-mysql-pro  mysqldump -t erp-dq-pro -u root -p123456  > /data/mysql/data/backup/${BACK_DATA}
#导出表结构及数据,xin-mysql为数据库名
docker exec -i xin-mysql-pro  mysqldump erp-dq-pro -u root -p123456  > /data/mysql/data/backup/${BACK_DATA}

12.8 Docker 安装启动

# sudo systemctl daemon-reload
Job for docker.service failed because the control process exited with error code. See "systemctl status docker.service" and "journalctl -xe" for details.

查看docker状态,来查找错误信息

systemctl status docker.service

发现错误信息为

Error starting daemon: SELinux is not supported with the overlay2 graph driver on this kernel. Either boot into a ne...led=false

vi /etc/sysconfig/docker

# selinux-enabled 主要是利用selinux机制限制docker容器内的进程访问宿主机/其它容器的资源。如果这个选项没有开启,那么容器自身的隔离机制是用户安全的唯一屏障,某些恶意程序在某些情况下可能会突破docker容器本身的资源隔离机制(以rootfs为主),访问到宿主机的资源。开启了这个选项后,即使恶意程序突破了rootfs的限制进入到宿主机的文件系统中,它所造成的破坏也是有限的,因为selinux机制限制了这个进程对宿主机文件的访问。
--selinux-enabled 设置为false

在这里插入图片描述

12.8 docker build

Error parsing reference: "openjdk:8 as builder" is not a valid repository/tag: invalid reference format

as builder, AS base, 使用 docker 的新特性 multi-stage build, 该特性要求 docker 17.05 或更高版本. 所以低版本会出现这个问题。

12.9 docker 运行错误

ERROR: Failed to Setup IP tables: Unable to enable SKIP DNAT rule:  (iptables failed: iptables --wait -t nat -I DOCKER -i br-02e3438401a6 -j RETURN: iptables: No chain/target/match by that name.

防火墙关闭之后 docker 需要重启

service docker restart

12.10 防火墙指定开放端口

查询 docker 的网卡

$ ip addr

在这里插入图片描述

将网卡添加到防火墙的 trusted 域中

$ firewall-cmd --permanent --zone=trusted --change-interface=docker0

# 有可能换需要添加 开放的端口 
$ firewall-cmd --zone=public --add-port=3308/tcp --permanent  
# 查看端口是否生效
$ firewall-cmd --zone=public --query-port=3308/tcp
# 查看开放的所有端口
$ firewall-cmd --zone=public --list-ports

重载 防火墙配置

$ firewall-cmd --reload

重启动docker

# 启动docker
systemctl restart  docker
# 查看docker 状态
systemctl status  docker

12.11 防火墙的设置导致docker 启动失败

[root@localhost bling]# journalctl -xe

在这里插入图片描述

解决办法:

  • 检查firewall-cmd中是否存在docker zone
firewall-cmd --get-active-zones

在这里插入图片描述

  • 如果 docker 区域可用,将接口更改为 docker0
sudo firewall-cmd --permanent --zone=docker --change-interface=docker0 
  • 重启
# 重新加载运行的配置 使得防火墙生效
firewall-cmd --reloadsudo systemctl restart firewalld
# 启动docker
systemctl start  docker
# 查看docker 状态
systemctl status  docker

12.12 docker 启动出错

在服务器上使用docker run启动容器时报错:

$ docker run -d --name redis -p 20100:6379 redis --requirepass compliance
>>> docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "process_linux.go:449: container init caused \"write /proc/self/attr/keycreate: permission denied\"": unknown.
ERRO[0000] error waiting for container: context canceled

**问题原因:**由于操作系统已启用SELinux,造成“/proc/self/attr/keycreate” 没有写入权限

# 使用  getenfor 命令查看 SELinux 运行模式
$ getenfor
>>> Enforcing

解决办法:

1> 永久方法(需要重启服务器)

# 修改 /etc/selinux/config 文件中设置 SELINUX=disabled ,然后重启服务器。
vim /etc/selinux/config

在这里插入图片描述

2> 临时方法 – 设置系统参数

# 使用命令 
# 设置SELinux 成为permissive模式
setenforce 0 

之后

在服务器上使用docker run启动容器时报错:

$ docker run -name redis -p6379:6379 --requirepass compliance
>>> Fatal: Can't initialize Background Jobs. Error message: Operation not permitted

问题原因:简单来说,似乎是 Redis 7.0.11 版本才會有,查看相关讨论后采用「Redis 7.0.10」版本,便能順利启动 Redis 容器并正常运作

12.13 docker 的 overlay2 占用 100%

参考资料

通过如下脚本可以寻找所以容器中系统日志占用的情况,通常是 *-json.log

for i in $(docker ps -q ); do
  echo "ContainerID: $i";
  ls -alh $(docker inspect $i | grep LogPath|awk -F "\"" '{print $4}');
done;

在这里插入图片描述

将占用最大的日志文件清空

cd  /var/lib/docker/overlay2

# 粗暴处理
echo "" > $dockerLogFile

在这里插入图片描述

13. Docker 的可视化工具

docker 可视化工具

13.1 LazyDocker

lazydocker HitHub 使用文档参照

docker run --rm -it -v \
/var/run/docker.sock:/var/run/docker.sock \
-v /yourpath:/.config/jesseduffield/lazydocker \
lazyteam/lazydocker

# /yourpath = 改成自己的path
docker run --rm -it -v \
/var/run/docker.sock:/var/run/docker.sock \
-v /home/chenglei/lazydocker:/.config/jesseduffield/lazydocker \
lazyteam/lazydocker

# 命令别名
alias lzd = docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock -v ~/.config/lazydocker:/.config/jesseduffield/lazydocker lazyteam/lazydocker

直接运行改命令,就可以下载docker镜像然后会运行打开一个可视化的界面。

14. 参考资料

docker 学习

docker 架构和工作原理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值