Docker容器和镜像教程【详细版】

一、参考资料

ubuntu16.04 docker tensorflow-gpu镜像下载与模型训练速度对比
ubuntu16.04-LTS+cuda-9.1+docker+tensorflow-gpu
docker-compose 一步步构建django + redis + mysql + nginx项目
Docker 中安装tensorflow
深度学习Tensorflow生产环境部署(上·环境准备篇)
深度学习Tensorflow生产环境部署(下·模型部署篇)
Docker 入门教程
快速入门Docker—用Docker搭建Python的开发环境
关于Docker目录挂载的总结
教你如何修改运行中的docker容器的端口映射
Docker 容器化技术介绍(八) 之 Docker 备份与迁移
docker容器中配置python环境

二、相关介绍

1. 仓库/镜像/容器

仓库:存放镜像的地方;

镜像(image):类似ppt模板,是容器的基础;image 文件是通用的,一台机器的 image 文件拷贝到另一台机器,照样可以使用。一般来说,为了节省时间,我们应该尽量使用别人制作好的 image 文件,而不是自己制作。即使要定制,也应该基于别人的 image 文件进行加工,而不是从零开始制作。

容器:根据ppt模板制作出来的具体的PPT,实际运行代码的执行环境,容器就是镜像的运行实例

Docker注册中心:如果我们是第一次通过某个镜像去启动容器,首先宿主机会去/var/lib/docker 目录下去找,如果没有找到,则会去registry 中去下载镜像并且存放于虚拟机,然后完成启动。registry 可以想象为一个镜像的仓库,默认的 registry 是 docker 官方提供的 registry 服务,名为 Docker Hub。当然,你也可以构建自己的镜像仓库。

2. 修改Docker权限

Docker 需要用户具有 sudo 权限,为了避免每次命令都输入sudo,可以把用户加入 Docker 用户组。

# 把用户加入 Docker 用户组
sudo usermod -aG docker $USER 

#更新用户组 
newgrp docker 

#测试docker命令是否可以使用
docker images    

3. Dockerfile 配置

Dockerfile 是文本文件,没有后缀名。
Docker容器和镜像教程【详细版】_第1张图片

FROM node:8.4
COPY . /app
WORKDIR /app
RUN npm install --registry=https://registry.npm.taobao.org
EXPOSE 3000


FROM node:8.4:该 image 文件继承官方的 node image,冒号表示标签,这里标签是8.4,即8.4版本的 node

COPY . /app:将当前目录下的所有文件(除了.dockerignore排除的路径),都拷贝进入 image 文件的/app目录

WORKDIR /app:指定接下来的工作路径为/app

RUN npm install:在/app目录下,运行npm install命令安装依赖。注意,安装后所有的依赖,都将打包进入 image 文件

EXPOSE 3000:将容器 3000 端口暴露出来, 允许外部连接这个端口

4. RUN与CMD的区别

RUN命令与CMD命令的区别在哪里?

简单说,RUN命令在 image 文件的 构建阶段执行,执行结果都会打包进入 image 文件;CMD命令则是在 容器启动后 执行。另外,一个 Dockerfile 可以包含多个RUN命令,但是只能有一个CMD命令

指定了CMD命令以后,docker container run命令就不能附加命令了,否则它会覆盖CMD命令。

5. 查看docker信息

Docker 常用命令与操作

# 查看docker信息
docker info

# 查看容器日志
docker logs -f <container_id> 

# 查看容器运行的各种数据
docker inspect <container_id> 

# 查看本容器ip
cat /etc/hosts

6. .dockerignore 配置文件

docker-.dockerignore 文件

.dockerignore 是文本文件,没有后缀名,与 git 工程中的 .gitignore 类似,.dockerignore 忽略表里的的文件或目录不会被docker打包构建。

.git
node_modules
npm-debug.log

# 上面代码表示,这三个路径要排除,不要打包进入 image 文件。如果你没有路径要排除,这个文件可以不创建。

6.1 .dockerignore 优点

  1. 构建镜像时能避免不需要的大文件上传到服务端,从而拖慢构建的速度网络带宽的消耗;
  2. 可以避免构建镜像时将一些敏感文件及其他不需要的文件打包到镜像中,从而提高镜像的安全性

7. 端口映射

Dockerfile 文件抛出的端口与flask绑定的端口一致,例如:

EXPOSE 5000
app.run(host='0.0.0.0', port=5000)

Dockerfile 文件抛出的端口与docker映射的端口一致。例如:

EXPOSE 5000
docker run -it -p 8080:5000 flaskweb:1.0.0

宿主机的 8080 端口和docker容器抛出的 5000 端口做了映射,访问宿主机的8080端口也即直接访问了docker容器中 5000 端口的flask app这个web应用。例如:

172.17.0.2:5000
127.0.0.1:8080
localhost:8080

如果宿主机是一个云主机或者云服务器,只要它有公网ip,就可以通过 宿主机ip:8080 就可以访问docker容器中开启的flask web服务了。
以上三个端口,可以相同,方便记忆管理。

8. Docker网络通信

Docker 网络有四种模式,分别为:hostcontainernonebridge模式。其中bridge模式为Docker默认的网络模式,Docker server在启动时便会创建一个名为docker0的虚拟网桥以给后续的容器提供网络桥接。其工作方式与交换机类似,将所有的容器连接在同一个二层网络当中,相应的容器使用分配的Ip进行IP通信,并在宿主机上做相应的DNAT和SNAT来使得容器Ip能够与外部宿主机网络通信。
Docker容器和镜像教程【详细版】_第2张图片
Docker容器和镜像教程【详细版】_第3张图片

9. Docker文件系统

Docker容器和镜像教程【详细版】_第4张图片

10. Docker 构建tomcat环境

Docker 容器操作 常用命令

11. overlay2

Docker:overlay2浅析

问题引入
Docker容器和镜像教程【详细版】_第5张图片
镜像可以理解为容器的模板一套镜像可以衍生出多个容器

那么多个容器势必有相同的镜像层,如果我们每次拷贝一份,那么对存储空间的要求的相当大的,并且也不利于后续的整合和发布,因为这样意味着当别人需要你的容器时,你commit的就是一整份镜像,这好比使用git时,当你需要获取origin的更新资源时,需要pull一整份代码下来。

因此,通过镜像层增量的方式来组织,使不同的docker容器可以共享相同的镜像层,再加上自己的改动进行发布。而docker就支持多种UnionFS,如aufs、overlay2等等。

三、Docker容器

Docker Hub 网址

1. docker服务相关

# 查看docker服务状态
systemctl status docker

# 启动docker服务
systemctl start docker

# 重启docker服务
systemctl restart docker

# 停止docker服务
systemctl stop docker

# 开机自启docker
systemctl enable docker

2. 查看容器相关

# 从 Docker Hub 网站搜索镜像
docker search [imageName]

# 查看docker信息 
docker info

# 查看正在运行的容器
docker ps

# 查看所有容器
docker ps -a

# 进入容器
docker exec -it <container_id> /bin/bash

# 进入一个正在运行的 docker 容器
# 如果docker run命令运行容器的时候,没有使用-it参数,就要用这个命令进入容器
docker container exec <container_id>

# 退出容器
exit

3. 启动容器相关

# 创建容器
docker run --rm --name=hello-world -w /usr/src/html --volume "$PWD/":/usr/src/html

--rm:停止运行后,自动删除容器文件
--name hello-world:容器的名字叫hello-world
-w /usr/src/html: 指定容器的 /usr/src/html 目录为工作目录
-v|--volume "$PWD/":/usr/src/html:将当前目录($PWD)映射到容器的/usr/src/html

# 如果本地没有image镜像,会自动从仓库抓取
docker run [imageName]

# 启动容器
docker run -p 8000:3000 -it [imageName]:5.7 -u root /bin/bash

-p参数:容器的 3000 端口映射到本机的 8000 端口,默认情况下容器中镜像占用的端口是 Docker 容器中的端口与外界是隔绝的,必须进行端口映射才能访问
在 Docker 容器的虚拟环境里面,进程接触到的文件系统和网络接口都是虚拟的,与本机的文件系统和网络接口是隔离的,因此需要定义容器与物理机的端口映射(map)
-i参数:运行容器
-t参数:交互式容器,表示容器启动后会进入其命令行,加入-it 这两个参数后,容器创建就能登录进去;即分配一个伪终端
-d参数:守护式容器,表示让容器在后台运行起来
-it|-id:交互式|守护式运行容器
-u参数:运行容器的时候,赋予 `root` 权限
[imageName]:5.7:image 文件的名字(如果有标签,还需要提供标签,默认是 latest 标签)
/bin/bash:容器启动以后,内部第一个执行的命令。这里是启动 Bash,保证用户可以使用 Shell

# 例如:
# 启动服务
docker run -t --rm -p 8501:8501 -v "$TESTDATA/saved_model_half_plus_two_cpu:/models/half_plus_two" -e MODEL_NAME=half_plus_two tensorflow/serving &

# 访问服务
curl -d '{"instances": [1.0, 2.0, 5.0]}' -X POST http://localhost:8501/v1/models/half_plus_two:predict
# 启动已停止运行的容器
docker start <container_id>  

# 重启容器
docker restart <container_id> 

# 停止容器
docker stop <container_id>

# 停止所有容器
docker stop $(docker ps -a -q)

# 查看所有服务
docker-compose ps

# 后台启动容器
docker-compose up -d 

# 以依赖性顺序 启动服务
docker-compose up -d

# 按依赖关系顺序 停止服务
docker-compose stop

# 杀死所有正在运行的容器
docker kill $(docker ps -a -q)

# 删除容器
docker rm <container_id>
docker rm -f <container_id> # 强制删除

# 删除所有容器
docker  rm $(docker ps -a -q)

4. docker容器间的IPC通信

  1. 容器间都共享宿主机的内存

    //所有容器启动时加入该参数
    docker run --ipc=host
    
  2. 共享其中某个容器的内存

    //启动容器1,将其设置为共享模式
    docker run -it --ipc=shareable --name ipc_container1 <container_id> /bin/bash
    
    //启动容器2,连接到容器1的内存
    docker run -it --ipc=container:ipc_container1 --name ipc_container2 <container_id> /bin/bash
    

5. 其他指令

# 查看容器的网络环境
docker inspect <container_id>

# 查看容器里面 Shell 的标准输出
# 如果docker run命令运行容器的时候,没有使用 -it 参数,就要用这个命令查看输出
docker container logs <container_id>

# 查看服务的日志
docker logs -f --tail=10 django_compose_django_1

# 在容器中安装vim
apt-get update
apt-get install vim

# 拷贝文件到容器
docker cp ./submit/xy2.py <container_id>:[/path/to/]

# 拷贝文件到宿主机
# 从正在运行的 Docker 容器,将文件拷贝到宿主机的当前目录
docker cp <container_id>:[/path/to/file] [/path/to/]

# 删除容器中文件 
docker rm <container_id>:[/path/to/file]

# 固化容器
# 把容器upbeat_pascal固化为image,名为success
docker commit upbeat_pascal success

# 查看docker容器ip
docker inspect <container id>

四、Docker镜像

1. 查看镜像相关

# 从 docker hub 中搜索镜像
docker search [imageName]
INDEX:索引;
NAME:镜像名称;
DESCRIPTION:描述;
STARS:关注人数,单位为 k;
OFFICIAL:是否为官方发布)[ok] 则表示此版本为官方发行版本;
AUTOMATED:是否自动配置,[ok] 则表示镜像已经自动配置好了,获取就能直接使用,否则需要自己手动配置;

# 查看镜像
docker images

# 查看portainer镜像
docker search portainer

# 下载portainer风格镜像
docker pull portainer/portainer 

2. 启动镜像相关

# 构建镜像
docker build -it [imageName]:5.6 .

-i 为交互式容器;
-t|--tag参数用来指定 image 文件的名字,后面还可以用冒号指定标签。如果不指定,默认的标签就是latest;
. 最后的那个点表示 Dockerfile 文件所在的路径
# 从仓库获取镜像
docker image pull [imageName]

# 查看镜像
docker images

# 运行镜像
docker run [imageName]

# 重启镜像
docker start [imageID]

# 停用镜像
docker stop [imageID]

# 开始构建生成镜像
docker-compose build 

# 以依赖性顺序启动服务
docker-compose up -d

# 按依赖关系顺序停止服务
docker-compose stop

# 删除镜像
docker image rm [imageID]
docker rmi [imageID]
docker rmi -f [imageID]

# 删除所有的镜像
docker rmi $(docker images -q)
docker rmi -f $(docker images -q)

3. 导入导出镜像

Docker 三大核心之镜像 基于本地模板导入创建镜像 export、import、save、load

容器迁移,先导出容器,再导入成镜像。

# 导出容器,打包并压缩
docker export <container_id> | gzip > image_name.tar.gz

# 导入镜像
cat image_name.tar.gz | docker import - [imageName]:版本号

# 使用 docker import 导入已下载的镜像
http://download.openvz.org/template/precreated/contrib/centos-6-x86_64-20170709.tar.xz
cat centos-6-x86_64-20170709.tar.xz | docker import - centos6
# 导出容器,打包为tar包
docker export <container_id> > flaskMCS.tar

# 导入tar包
# 从flaskMCS.tar中加载镜像,镜像名为flaskmcs:V1.0.1
docker cat flaskMCS.tar | docker import - flaskmcs:v1.0.1
# 使用 docker export 导出镜像
docker export [imageID] > /PATH/TO/securitit-centos7.tar

# 使用 import 导入镜像
docker import - securitit-centos7 < /PATH/TO/securitit-centos7.tar
# 使用 docker save 导出镜像
# 导出镜像
docker save [imageName]:版本号 -o image_name.tar

# 保存镜像到指定路径
docker save [imageName]:版本号 > /PATH/TO/image_name.tar

# 多个镜像打包到一起
docker save [imageID] [imageID] -o image_name.tar

# 导入镜像
docker load -i image_name.tar

# 导入指定路径的镜像
docker load < /PATH/TO/securitit-centos7-01.tar

4. 其他指令

# 启动dockerui容器
docker run -d --name portainerUI -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer

# 浏览器访问 http://192.168.2.119:9000 , 设置一个密码即可,点击创建用户

五、常用指令

1. 查看docker磁盘使用情况

docker system df
[root@localhost ~]# docker system df
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              84                  36                  13.75GB             4.876GB (35%)
Containers          117                 66                  14.86GB             70.13MB (0%)
Local Volumes       0                   0                   0B                  0B
Build Cache         0                   0                   0B                  0B
[root@localhost ~]# du -hs /var/lib/docker/
56G     /var/lib/docker/

2. 清理容器

# 清理磁盘、删除关闭的容器、无用数据卷和网络以及dangling镜像
docker system prune

# 批量删除所有孤儿的volume
docker volume rm $(docker volume ls -q)

六、可能出现的问题

Q: [ERROR] --initialize specified but the data directory has files in it. Aborting.

错误原因:
数据目录中有文件,初始化出错

解决方法:
将数据目录下已存在的文件全部删除

Q: docker基础容器中bash: vi及ll: command not found问题解决

docker基础容器中bash: vi及ll: command not found问题解决

错误原因:
vim没有安装,ll没有打开

解决方法:
# 安装vim
apt-get install vim

# 修改 .bashrc 配置文件
vim ~/.bashrc
末尾添加 alias ll='ls -l'

# 执行立即生效
source ~/.bashrc

# 至此,ll和vim都可以用了

Q: docker permission denied权限

[Linux] docker 出现Got permission denied while trying to connect to the Docker daemon socket…问题的解决办法

Got permission denied while trying to connect to the Docker 
daemon socket at unix:///var/run/docker.sock: Get 
"http://%2Fvar%2Frun%2Fdocker.sock/v1.24/images/json": dial unix 
/var/run/docker.sock: connect: permission denied
错误原因:
docker进程使用Unix Socket而不是TCP端口,而默认情况下,Unix socket属于root用户,需要root权限才能访问。

解决办法:
1. 使用sudo获取root权限运行  
2. docker守护进程启动的时候,会默认赋予名字为docker的用户组读写Unix socket的权限,因此只要创建docker用户组,并将当前用户加入到docker用户组中,那么当前用户就有权限访问Unix socket了,进而也就可以执行docker相关命令

Q: /var/lib/docker/overlay2 占用很大

/var/lib/docker/overlay2 占用很大,清理Docker占用的磁盘空间,迁移 /var/lib/docker 目录

【docker】 /var/lib/docker/overlay2/ 占用磁盘问题

待测试

你可能感兴趣的:(运维,Docker)