Docker 汇总
1. 简介
docker官网
docker文档
阿里云镜像搜索
查询所有镜像
容器话技术很早就出现过,如 OpenVZ,LXC,RKT等
1.1 容器是什么
虚拟机
虚拟机代表: VMWare, OpenStack, 模拟运行一整套操作系统(包括内核, 应用运行态环境和其它系统环境)和跑在上面的应用.
容器
container,独立运行的一个或者一组应用, 以及他们必需的运行环境。 容器是Pass(platform-as-a-service)的一种体现。 通俗的说容器是一种沙盒技术或者说是个轻量级的虚拟机。
容器是为了解决 “在切换运行环境时,如何保证软件能够正常运行” 的问题。
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有两个版本 社区版(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
export | save |
---|---|
针对的是容器 | 针对的是镜像 |
导出的文件体积小 | 导出的文件体积大 |
可以为镜像指定新名字 | 不能对载入的镜像命名 |
不支持多个镜像打入一个包 | 支持多个镜像打入一个包 |
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
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 的配置来生成镜像的。
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 参数简介
参数 | 描述 |
---|---|
image | image是指定服务的镜像名称或镜像ID。如果镜像在本地不存在,Compose将会尝试拉取镜像。 |
build | 服务除了可以基于指定的镜像,还可以基于一份Dockerfile,在使用up启动时执行构建任务,构建标签是build,可以指定Dockerfile所在文件夹的路径。Compose将会利用Dockerfile自动构建镜像,然后使用镜像启动服务容器。 |
context | context选项可以是Dockerfile的文件路径,也可以是到链接到git仓库的url,当提供的值是相对路径时,被解析为相对于撰写文件的路径,此目录也是发送到Docker守护进程的context |
dockerfile | 使用dockerfile文件来构建,必须指定构建路径 |
commond | 使用command可以覆盖容器启动后默认执行的命令。 |
container_name | Compose的容器名称格式是:<项目名称><服务名称><序号> 可以自定义项目名称、服务名称,但如果想完全控制容器的命名,可以使用标签指定 |
depends_on | 在使用Compose时,最大的好处就是少打启动命令,但一般项目容器启动的顺序是有要求的,如果直接从上到下启动容器,必然会因为容器依赖问题而启动失败。例如在没启动数据库容器的时候启动应用容器,应用容器会因为找不到数据库而退出。depends_on标签用于解决容器的依赖、启动先后的问题 |
PID | 将PID模式设置为主机PID模式,跟主机系统共享进程命名空间。容器使用pid标签将能够访问和操纵其他容器和宿主机的名称空间。 |
ports | ports用于映射端口的标签。 |
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 镜像分层与共享
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
目录 | 描述 |
---|---|
lower | lower 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 的可视化工具
13.1 LazyDocker
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镜像然后会运行打开一个可视化的界面。