Docker安装与使用
平台:Ubuntu18.04 —— 主要参考:菜鸟教程
Docker 包括三个基本概念:
- 镜像(Image):镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。
- 容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
- 仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像
注意镜像和容器的区别,是用run启动镜像,得到一个对应的容器,容器停止后可以用start启动。镜像名 ≠ 容器名,镜像ID ≠ 容器ID;
镜像系统一般都需要apt update一下
一、安装docker工具
1. 按 菜鸟教程 中“Ubuntu Docker 安装——手动安装 ”的指导进行。
执行测试
sudo docker run hello-world # 报错是由于官方源在国外,无法连接 Unable to find image 'hello-world:latest' locally docker: Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers).
2. 添加国内源,重新尝试即可。 ——参考
sudo vim /etc/docker/daemon.json # 编辑配置文件,163的挺好用 # 添加下面的内容 { "registry-mirrors": ["https://registry.docker-cn.com","http://hub-mirror.c.163.com"] } sudo systemctl restart docker.service # 重启docker服务
3. 添加当前用户到docker用户组 ——参考
docker默认属于root用户,其它用户要使用docker命令需要sudo权限。可以将需要的账号添加到docker用户组下,就不必每次都用sudo了。
cat /etc/group # 查看有哪些分组 sudo usermod -aG docker username # 将username用户添加到docker分组里 newgrp docker # 更新分组信息
docker run hello-world # 测试
**** 离线安装docker**** —— 参考我的另一篇博客
二、 常用命令
1. 常见操作
docker ps # 查看正在运行的容器
# 输出的PORTS信息表示的是 容器端口 -> 主机端口 的映射关系
docker rm container_name/id # 删除容器(需要先停止)
docker rmi image_name/ID # 删除镜像
docker run image_name/ID # 运行镜像生成容器,有时候运行失败也会生成一个容器
docker run -it ubuntu /bin/bash # -i:交互式,-t:终端,即启动镜像ubuntu并进入其命令行终端shell:/bin/bash;这时exit后容器将停止(exited)
docker logs container_name/ID # 查看容器内的标准输出
docker stop container_name/ID # 停止运行容器
docker start container_name/ID # 启动一个已经停止运行容器
docker restart container_name/ID # 重启容器
docker exec -it container_name/ID /bin/bash # 进入已启动的容器的终端,这时exit后容器还在后台运行(Up)
# 镜像与容器重命名
docker tag image_id new_image_name # 镜像重命名/增加新指引label,这之后将有两个镜像名称指向一个镜像id,可以删掉其中一个名称 ——参考
docker rename container_name new_container_name # 容器重命名,容器名用 docker ps -a 可以看到,NAMES(这个名称一般是随机生成的)
# 镜像打包与加载
docker save image_name/ID -o filename.tar # 镜像打包的内容包括各种历史记录,会比较大
docker load -i filename.tar # 镜像load后还是原来的名称
# 容器打包与加载
docker commit container_name/ID image_name:version # 把容器打包为镜像
docker export container_name/ID > exportname.tar # 导出为tar包
docker import exportname.tar new_image_name:version # 导入容器为新镜像,可以定义新镜像名
** 添加随docker启动而自启动服务的方法
添加一个执行相关功能的脚本start.sh,在/root/.bashrc末尾添加如下一行,则启动docker而根据/root/.bashrc初始化时,将执行相关脚本。
source 'full/path/to/start.sh'
2. 主机与docker容器之间的文件传输(容器间不行) ——参考
# 容器中不存在的目录将自动创建
# 在宿主机目录,向容器传输文件 docker cp path/to/file container_name:/target/path/ # "/target/path/"必须存在并以反斜杠 / 结尾,否则只会在target/目录下形成一个叫 path 的文件
# 在宿主机目录,从容器向宿主机传输文件
docker cp dockername:/path/to/file target/path
** 注意,通过软链接链接到容器外部的文件时,这些外部文件在容器内是无法访问的,容器中会解析链接到的路径,而外部文件的路径一般在容器内是不存在的
** 挂载主机目录到容器 ——详解;
docker run -it -v /path/of/source/directoy:/target/path/in/container image_name/ID /bin/bash # source在宿主机上,两边的路径都用绝对路径
注意:容器内一般对挂载的目录没有写的权限,是因为内部用户的uid和主机中用户的uid不同 ——参考博客
可以更改docker内部用户的uid,来达到统一(新建了非root用户)
# 主机操作 id username # 查看用户的uid # docker内操作 id newuser usermod -u 1000 newuser # 1000是主机中用户username的uid ——参考博客
** 一个例子
主机上有目录 /home/work,容器导出的镜像内有新建的目录 /home/job,里面是向容器内新加的文件,
docker run -it -v /home/work/:/home/ image_name/ID /bin/bash # × 容器内 /home/job目录不见了(看不到,ls不了),因为主机的相关目录挂载到容器内的/home/下面了,和job同级,都在/home/目录下,job目录被掩盖了(实际上还在) docker run -it -v /home/work/:/home/job/ image_name/ID /bin/bash # √ 容器内 /home/job目录还在,可以正常使用
3. 常用工具安装
apt install vim # 默认不包含vim
4. 在docker安装驱动时出现问题 —— 问题暂未解决
“An NVIDIA kernel module 'nvidia-uvm' appears to already be loaded in your kernel. This may be because it is in use (for example, by an X server, a CUDA program, or the NVIDIA Persistence Daemon), but this may also happen if your kernel was configured without support for module unloading...."
lsmod | grep nvidia # 查看nvidia的相关module,输出依次为:Module, Size, Used, by
5. 端口映射
端口映射用参数-p,-p source_ip:source_port:docker_port, ——参考博客,更多参看菜鸟
docker run -it -p 100:100 image_name/id /bin/bash # 将主机上所有地址的100端口映射到容器的端口100 docker run -it -p 127.0.0.1:200:100 image_name/id /bin/bash # 将主机回环地址127.0.0.1的200端口映射到容器的端口100 docker run -it -p host_ip:300:123 imame_name/id /bin/bash # 将主机的网络地址的300端口映射到容器的端口123上,网络上可以通过host ip访问到主机 ==》所有向host_ip:300端口的请求都会转到容器的端口123上
第三种映射方法里,相当于容器也有了一个对外网的ip,虽然只有端口300可用(映射到内部123)
6. 同步docker内时间与宿主机时间 ——参考博客
docker cp -L /usr/share/zoneinfo/Asia/Shanghai container_name/id:/etc/localtime
二、安装nvidia-docker —— 参考我的另一篇博客