Docker是基于容器的,直接用带有相应功能的镜像就行,而不必运行Docker容器来自己搭建环境那么麻烦。
Docker 中文网 http://www.docker.org.cn

两小时入门 Dockerhttps://mp.weixin.qq.com/s/eAJpnEfjflVr76iPVHN6rA

容器操作

容器管理

docker容器可以理解为在沙盒中运行的进程。这个沙盒包含了该进程运行所必须的资源,包括文件系统、系统类库、shell 环境等等。但这个沙盒默认是不会运行任何程序的。你需要在沙盒中运行一个进程来启动某一个容器。这个进程是该容器的唯一进程,所以当该进程结束的时候,容器也会完全的停止。

常用操作

# 停止、启动、重启、杀死一个容器、创建容器(不启动)、只看端口信息
docker stop Name/ID
docker start Name/ID
docker restart Name/ID
docker kill Name/ID
# -t, --time=10** Number of seconds to try to stop for before killing the container, Default=10
docker create --name XXXX Name/ID
docker port Name/ID

# 列出当前所有正在运行的容器
docker ps
参数:
-a      #列出所有容器(包括暂停、停止的)
-f      #根据条件过滤显示内容
-l      #列出最近创建的容器
-n      #列出最近创建的N个容器,N为数字
-q      #只显示容器ID
-s      #显示总文件大小


##############################################################################################
# 启动、运行容器
# 启动容器
注意:centos镜像启动时使用--privileged参数,启动/usr/sbin/init ,才可在容器中使用systemctl管理服务
docker run --privileged -idt [镜像ID]
参数:
-d              #后台运行容器,并返回容器ID
-i              #以交互式模式运行容器,常与-t参数同时使用
-t              #给容器重新分配一个伪终端,常与-i参数同时使用
--name          #给容器指定一个名称
-m              #指定容器使用内存的最大值
--net           #指定容器使用的网络类型
--link          #链接到另一个容器

# 在容器中执行命令,输出结果 
docker run image_name echo "hello word"
docker run image_name apt-get install -y nginx
Note: 在执行apt-get 这样的命令的时候,要带上-y参数。如果不指定-y参数的话,apt-get命令会进入交互模式,需要用户输入命令来进行确认,但在docker环境中是无法响应这种交互的。apt-get 命令执行完毕之后,容器就会停止,但对容器的改动不会丢失。



##############################################################################################
# 进入容器
#法一:交互式进入容器中(启动并进入容器)
docker run -it [容器ID] /bin/bash

#法二:交互式进入容器中(启动容器后进入容器)
docker exec -it [容器ID] /bin/bash
参数:
-d      #在后台运行
-i      #保持STDIN打开
-t      #分配一个伪终端

以上两种exit退出后不影响容器运行。
法三,只要这个连接终止,或者使用了exit命令,容器就会退出后台运行,如果不想退出,可以按Ctrl+p+q快捷键,让容器保持后台运行。

#法三:
docker attach ID
参数:
 --no-stdin=false** Do not attach stdin; 
 --sig-proxy=true** Proxify all received signal to the process  

Note: attach命令允许你查看或者影响一个运行的容器。你可以在同一时间attach同一个容器。你也可以从一个容器中脱离出来,是从CTRL-C。


##############################################################################################
# 保存对容器的修改(打包容器),修改镜像名称
当你对某一个容器做了修改之后(通过在容器中运行某一个命令),可以把对容器的修改保存下来,这样下次可以从保存后的最新状态运行该容器。
## 保存对容器的修改
docker commit xxx(容器ID) new_image_name:tag
例:docker commit c5c56629cbe0 leolan/centos7:v1.0

参数:
-a      #提交的镜像作者
-c      #使用Dockerfile指令来创建镜像
-m      #提交时附上说明文字
-p      #在commit时,将容器暂停

修改镜像名称可以在原来镜像的基础上commit成新镜像,打标签,这时再删除旧的镜像就行了。

挂载目录

docker run -d -i -p 8888:80 -v /mnt:/home/wwwroot 0fd0ae97f1a4 /bin/bash
# 把宿主机的/mnt挂载到容器的网站目录,一定要在镜像名(IMAGE ID的前面,不然会启动不了)

目录挂载:http://www.linuxidc.com/Linux/2015-09/123519.htm
挂载后再增加挂载目录:http://www.open-open.com/lib/view/open1421996521062.html

容器缩小、扩容

docker容器默认创建的硬盘空间是10G,改变方式有两种。
1,新建容器时设置

新建容器时用参数指定,如:--storage-opt size=20G

或修改配置文件,让每次创建容器都是设置的大小:
vim /etc/sysconfig/docker-storage
DOCKER_STORAGE_OPTIONS="--storage-opt dm.basesize=20G"

systemctl restart docker

2,对已有容器修改(一般用于已有的容器空间不够用了,可以直接不重启容器无缝扩容)
**宿主机要为ext2、ext3、ext4格式,**因为xfs格式无法缩小空间。

# 修改池空间大小
这一步可以不做的,默认的池是够用的,如果不够用修改了,要重启docker服务才能生效。
首先,修改空间大小,必需使Docker运行在daemon环境下,即先停止正在运行的docker服务:
systemctl stop docker
然后使用命令使用daemon环境下运行docker:
docker -d

dd if=/dev/zero of=/var/lib/docker/devicemapper/devicemapper/data bs=1G count=0 seek=1000
dd if=/dev/zero of=/var/lib/docker/devicemapper/devicemapper/metadata bs=1G count=0 seek=10
上面的1000为1TB大小,即为数据池空间大小为1TB,而10则为Metadata的空间大小,10GB

从运行完后,使用命令查看docker池空间大小:
docker info
可以看到池空间已经被设置为data=1TB和metadata=10GB



# 连接进宿主机df -h查看磁盘信息。找到类似如下:
docker-8:4-1610614383-c0850e6fedcf9499dfeb01d9c0147c6bd5a0051ed44f0e65937cc191e8fdb5af

# 在宿主机下找到对应的卷:
ll /dev/mapper/docker-*

# 查看卷信息
dmsetup table docker-8:4-1610614383-c0850e6fedcf9499dfeb01d9c0147c6bd5a0051ed44f0e65937cc191e8fdb5af

0 146800640 thin 253:0 50
146800640是指设备的大小,表示有146800640个 512-bytes 的扇区,所以卷的大小略高于 10GB 的大小。

# 计算扇区(20G)
echo $((20*1024*1024*1024/512))

41943040

# 只修改设备的大小(只改大小,其他参数和原来的一样)
echo 0 41943040 thin 253:0 50 | dmsetup load docker-8:4-1610614383-c0850e6fedcf9499dfeb01d9c0147c6bd5a0051ed44f0e65937cc191e8fdb5af

# 修改卷大小(执行完之后就扩容成功了)
resize2fs docker-8:4-1610614383-c0850e6fedcf9499dfeb01d9c0147c6bd5a0051ed44f0e65937cc191e8fdb5af

参考:
http://baijiahao.baidu.com/s?id=1589433496639299184&wfr=spider&for=pc
https://blog.csdn.net/chengxuyuanyonghu/article/details/76560166


容器信息管理

# 查看容器配置信息(元数据)
docker inspect Name/ID
参数:
-f        #指定返回值格式或模板文件
-s        #显示总文件大小
--type    #为指定类型返回JSON
可以查看容器的配置信息,包括数据文件夹挂载路径:volume字段 有显示挂载的host路径。


# 从一个容器中读取日志
docker logs Name/ID
参数:
-f        #跟踪日志输出
-t        #显示时间戳
--tail    #只显示最新n条容器日志
--since   #显示某个开始时间的所有日志
 

# 列出一个容器里面被改变的文件或者目录
docker diff Name/ID
(list列表会显示出三种事件,A 增加的,D 删除的,C 被改变的)


# 显示一个运行的容器里面的进程信息  
docker top Name/ID


# 从容器里面拷贝文件/目录到本地一个路径  
docker cp Name:/container_path to_path
或者:
docker cp ID:/container_path to_path
例:docker cp 0ba76bea9688:/home/jiradb_$(date +%Y%m%d).sql /home

删除容器

# 删除单个容器(容器要先停止,注意是容器,不是镜像)
docker rm Name/ID
参数:
-f     #强制删除一个运行中的容器
-l     #删除指定的链接
-v     #删除与容器关联和卷


# 删除所有容器
docker rm `docker ps -a -q`

# -q参数能显示容器的ID,例如,批量删除<none>的镜像
docker ps -a -q |grep none|awk '{print $3}'|xargs docker rm
(删除的是容器,而不是镜像;注意容器和镜像的区别,一个镜像可以创建多个容器。删除镜像用rmi命令)

导入导出

当需要把一台机器上的镜像迁移到另一台机器的时候,需要保存镜像与加载镜像。

# 镜像(镜像存储文件,保留元信息和用户文件)
# 导出容器镜像到一个tar包
docker save [容器ID] -o /root/ubuntu001.tar
参数:
 -o, --output=""  Write to an file

# 加载(导入)一个tar包格式的镜像
docker load -i /root/ubuntu001.tar
参数:
 -i, --input=""  Read from a tar archive file
参考:http://www.cnblogs.com/boshen-hzb/p/6373549.html

##############################################################################################
# 快照(只保留快照信息,不保留文件和元信息)
# 导出
docker export [容器ID] > /root/ubuntu.tar

# 导入
cat ubuntu.tar | docker import - test/ubuntu:v1.0
# 此外,也可以通过指定 URL 或者某个目录来导入,例如
docker import http://example.com/exampleimage.tgz example/imagerepo


注:用户既可以使用 docker load 来导入镜像存储文件到本地镜像库,也可以使用 docker import 来导入一个容器快照到本地镜像库。
这两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息(即仅保存容器当时的快照状态),而镜像存储文件将保存完整记录,体积也要大。此外,从容器快照文件导入时可以重新指定标签等元数据信息。

已启动容器调整

Linux

# 先停止docker
systemctl stop docker

# 调整已启动的容器端口
vim /var/lib/docker/containers/[容器ID]/hostconfig.json

# 9000是容器内端口;9001是映射出来的端口
"PortBindings":{"9000/tcp":[{"HostIp":"","HostPort":"9001"}]},


# 开机自启
# 设置值为always,不开启则留空
"RestartPolicy":{"Name":"always","MaximumRetryCount":0},

# 启动docker
systemctl start docker

参考:https://www.cnblogs.com/shijf/p/10386193.html

Mac

Mac系统如果安装的是Docker Desktop这个软件,本质上是一个虚拟机来的,在Mac上虚拟Linux并在linux里运行Docker;所以修改配置要先进入虚拟机里面。

# 查看容器ID
docker container inspect mysql
或
docker ps

cd ~/Library/Containers/com.docker.docker/Data/vms/0/
在这个目录下面,有一个tty的文件,通过这个文件我们能够登录到docker内部的linux界面,然后使用下面命令进行登录:
screen tty

执行之后就登录虚拟机了,接下来的操作和Linux的是一样的
vi /var/lib/docker/containers/[容器ID]/config.v2.json

vi /var/lib/docker/containers/[容器ID]/hostconfig.json

修改完成后退出虚拟机
按Ctrl+A,然后快速按D,退出screen命令。
然后,使用screen -ls命令,查看当前会话:
看到类似:90029.ttys003.macdeMac-mini,其中90029就是进程号,kill掉
之后重启docker引擎(注意是重启Docker Desktop,而不是重启容器)

参考:https://my.oschina.net/fxtxz2/blog/3078882


关于Docker运行应用慢、卡顿的解决方案

因Mac和Linux文件系统的差异,Docker for Mac本质是在Mac上跑Linux以此来运行Docker服务端。对于需要频繁修改文件的框架来说,同步文件需要巨大的时间开销。需要解决的就是文件同步问题(默认的同步方式时间开销太大,需要引入新的同步方法)。

注意,以下方法在大量文件修改时有一定几率出现不同步或2-3秒后才刷新的问题;也和IDE是否实时保存文件有一定关系;正常使用不会感觉到差异!


法一(推荐):
此为Docker官方建议的方法:
如果还没有启动容器,可以通过“cached”选项开启
在启动容器时挂载目录时指定即可:-v /xxx/project:/www/wwwroot:cached

如果已经启动了容器,则需要修改容器配置:
此为Mac的修改方法

docker ps 记下容器id
cd ~/Library/Containers/com.docker.docker/Data/vms/0/
screen tty # 回车两次才会登录到Linux

# 以下两个文件都是json格式的
# 修改config.v2.json,
在"Propagation"前添加"Relabel":"cached",
vi /var/lib/docker/containers/[容器ID]/config.v2.json

# 修改hostconfig.json
在挂载目录后加cached;例:/xxx/project:/www/wwwroot:cached
vi /var/lib/docker/containers/[容器ID]/hostconfig.json

修改完成后退出虚拟机
按Ctrl+A,然后快速按D,退出screen命令。
然后,使用screen -ls命令,查看当前会话:
看到类似:90029.ttys003.macdeMac-mini,其中90029就是进程号,kill -9 90029 杀掉进程
之后重启docker引擎(注意是重启Docker Desktop,而不是重启容器)

参考:https://learnku.com/articles/31919


法二:
**有更新,请查看:**https://www.leolan.top/index.php/posts/306.html#directory0187352734446404321

使用docker-sync;需要安装一些依赖及下载docker镜像等,不是很方便。
Github:https://github.com/EugenMayer/docker-sync
官方文档:https://docker-sync.readthedocs.io/en/latest/index.html

# 安装docker-sync
sudo gem install docker-sync

# 安装;unison、sync二选一
brew install unison
brew install eugenmayer/dockersync/unox
或
brew install rsync

# 在项目根目录创建docker-sync.yml文件,文件模板见参考链接
启动方式一般用docker-compose,在项目根目录编写docker-compose.yml

# 启动容器即可,双向自动同步

参考:
https://blog.wangmao.me/use-docker-sync-for-macos.html
https://ruby-china.org/topics/37289



镜像操作

# 检索、搜索image  
docker search image_name

# 下载image  
docker pull image_name

# 列出镜像列表  
docker images
参数:
-a                #列出所有的镜像(含中间映像层,默认,过滤掉中间映像层);
--digests         #显示镜像的摘要信息;
-f                #显示满足条件的镜像;
--format          #指定返回值的模板文件;
--no-trunc        #显示完整的镜像信息;
-q                #只显示镜像ID。

# 删除一个或者多个镜像
docker rmi image_name
docker rmi -f `docker images -q`    #强制删除所有镜像,-f是强制执行

参数:
-f,              #强制删除
--no-prune=false #Do not delete untagged parents  

# 查看指定镜像的创建历史
docker history image_name
参数:
-H               #以可读的格式打印镜像大小和日期,默认为true;
--no-trunc       #显示完整的提交记录;
-q               #仅列出提交记录ID。

##############################################################################################
# 根据Dockerfile 构建出一个容器
docker build -t image_name -f Dockerfile_path Path
例:docker build -t mysql5.7 -f /root/Dockerfile ./

参数:
-f                        #指定要使用的Dockerfile路径
--label=[]                #设置镜像使用的元数据;
-m                        #设置内存最大值
--memory-swap             #设置Swap的最大值为内存+swap,"-1"表示不限swap
--no-cache                #创建镜像的过程不使用缓存
--pull                    #尝试去更新镜像的新版本
-q                        #安静模式,成功后只输出镜像ID
--rm                      #设置镜像成功后删除中间容器
--ulimit                  #Ulimit配置

##############################################################################################
# 发布镜像到互联网
# 发布到Docker hub
## 登陆/登出registry server
docker login
docker logout

参数:
 -e, --email=""  Email
 -p, --password=""  Password
 -u, --username=""  Username

## 登录/登出hub.c.163.com
docker login -u [你的网易云邮箱账号或手机号码] -p [你的网易云密码] hub.c.163.com
docker logout


## 打标签,发布docker镜像
如果是正在运行的容器,用以下方法
docker commit [容器ID] [容器名(例):hub.c.163.com/leolan/Ubuntu16:v2.0.3]
docker push [容器名(例):hub.c.163.com/leolan/Ubuntu16:v2.0.3]

如果已经是镜像了,可以直接推送,因仓库不同可以修改tag
docker tag [镜像ID] [带地址的新名称,如:docker.io/leolan/python3-jupyter-nginx]
docker push [镜像名,注意不是镜像ID]
使用tag只是名称不同,镜像ID是一样的,删除任何一个镜像都是无法删除的,需要使用-f参数强制执行。

Docker技术基础梳理

Docker技术基础梳理:https://mp.weixin.qq.com/s/bQPyg1mpwTMRr2wuSuGuqg
镜像管理:https://mp.weixin.qq.com/s/YjJfOvzLcrTIIW_qP113WA
容器生命周期管理:https://mp.weixin.qq.com/s/W8g9YXPcI_u-okXAbfXg1A
深入理解镜像与容器:https://mp.weixin.qq.com/s/aK48pks9Gqn3inwY9IxoUQ
Docker网络管理:https://mp.weixin.qq.com/s/5X4U-ow_opXCtk3LvjuQVA



资源限制

CPU限制:https://www.cnblogs.com/sparkdev/p/8052522.html
内存限制:http://www.cnblogs.com/sparkdev/p/8032330.html
存储空间限制:



参考资料:

搭建Docker环境:
搭建Java Web环境:http://www.open-open.com/lib/view/open1422413794439.html
Docker搭建私有仓库:http://blog.csdn.net/wangtaoking1/article/details/44180901
搭建WordPress站点:https://linux.cn/article-5560-1.html
非常详细的 Docker 学习笔记:http://www.open-open.com/lib/view/open1423703640748.html#articleHeader21
Dockerfile中CMD与ENTRYPOINT指令的比较:http://www.cnblogs.com/lienhua34/p/5170335.html

docker常用命令、一些坑:
http://www.cnblogs.com/ivictor/archive/2015/09/08/4791274.html
http://blog.csdn.net/wsscy2004/article/details/25878363



报错

启动容器时报错

报错:WARNING: IPv4 forwarding is disabled. Networking will not work.
解决:

vim /usr/lib/sysctl.d/00-system.conf

# 添加一行代码:
net.ipv4.ip_forward=1

重启network服务
systemctl restart network

容器故障导致无法启动实例

如果是容器配置突然出来问题,导致无法启动容器。

解决思路暂有两个:

**方法一:**把这个问题容器用docker commit提交到一个新的镜像,然后用docker run -i -d基于新镜像运行一个临时终端进去改变配置文件,然后把临时终端的id提交到一个新的镜像,然后在基于新的镜像重新启动容器。(这个方法步骤多,而且提交了新的镜像,对于后续维护增加了复杂性)
**方法二:**直接改变容器里的配置文件,不需要新提交镜像。

容器的数据是存储在本机的,内容也是和普通的文件系统基本一致。
查看容器ID,通过find找到容器存储目录。直接修改配置文件即可。然后重新启动容器。

参考:http://blog.51cto.com/yangrong/1596212


启动、创建容器报错

因根分区空间不足无法使用ssh连接,强制重启后通过ssh连接并对根分区(xfs格式)进行扩容,操作完成后发现docker部分容器启动失败,手动启动报以下错误。

起初以为是分区损坏,尝试用xfs_repair 方式修复,报错了,提示-L暴力修复(千万不要这么做,数据应该基本全丢)。

docker inspect [容器ID]  # 查看详细信息
xfs_repair /var/lib/docker/devicemapper/mnt/                                                                                                0ba4125de4b266de0545a2815a81377420d262ee6b2186876dc1fe39fbf6ce44
# 启动容器
devmapper: Error mounting '/dev/mapper/docker-253:3-102240090-49d5e316f143ebbc7223de5702dec29a9b2fb95490147da1b58b5912fa8722a0' on '/var/lib/docker/devicemapper/mnt/49d5e316f143ebbc7223de5702dec29a9b2fb95490147da1b58b5912fa8722a0'. fstype=xfs options=nouuid: input/output error
<4>[ 1968.545967] XFS (dm-5): log mount/recovery failed: error -5
<4>[ 1968.546057] XFS (dm-5): log mount failed",

# 创建容器
failed to register layer: devicemapper: Error running deviceCreate (createSnapDevice) dm_task_run failed

原因:猜测是暴力重启导致的元数据损坏,找到以下方法,修复后容器正常启动了,不确定数据是否都是(小改动很久远了,忘记了)

systemctl stop docker
thin_check --clear-needs-check-flag /var/lib/docker/devicemapper/devicemapper/metadata
thin_check /var/lib/docker/devicemapper/devicemapper/metadata
systemctl start docker

参考资料:
https://github.com/docker/for-linux/issues/46
https://bodhileafy.wordpress.com/2018/04/20/docker-error-running-devicecreate-createsnapdevice-dm_task_run-failed/

文章作者: Leo
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 LeoLan的小站
虚拟化 docker Docker常用命令、报错
喜欢就支持一下吧