docker基础及常见问题

我们常说的Docker是指Docker引擎(Engine),主要包含
1、Docker Daemon — docker守护进程(Server)
2、Docker REST API — 和docker daemon交互的REST API (用python或Go程序调用API和Daemon交互)
3、Docker CLI — 命令行应用 (我们执行docker run 等命令,用来和Daemon交互)

Docker服务端提供了一系列REST API(Docker Remote API),当我们敲入docker命令时实际上是通过API和Docker服务端进行交互。官方提供了三种链接方式:
a. unix:///var/run/docker/sock(默认连接方式)
b. tcp://host:port
c. fd://socketfd
本篇整理了docker常用命令及遇到的问题。

centOS7下安装docker

安装基本依赖 sudo yum install -y yum-utils device-mapper-persistent-data lvm2
设置即将安装的是稳定版仓库 sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
(该步骤可不选)edge月更新仓库 sudo yum-config-manager --enable docker-ce-edge
安装之前可以查看所有仓库中所有docker版本 yum list docker-ce --showduplicates | sort -r
默认安装使用命令 yum install docker-ce -y
安装完成启动 systemctl start docker 并设置开机自启动 systemctl enable docker
docker安装时默认创建了docker用户组,将普通用户加入docker用户组就可以不使用sudo来操作docker。使用命令 sudo usermod -aG docker xugz加入,需要重新登录或者执行 newgrp docker 改变当前用户的有效群组才能生效。
到这里没有异常的话,使用 docker version 验证安装是否成功

安装过程同时可以参照阿里云的帮助文档

centOS8安装docker

卸载旧版本 较旧的 Docker 版本称为 docker 或 docker-engine 。如果已安装这些程序,请卸载它们以及相关的依赖项
安装步骤
下载docker-ce的repo curl https://download.docker.com/linux/centos/docker-ce.repo -o /etc/yum.repos.d/docker-ce.repo
安装依赖(这是相比centos7的关键步骤) yum install https://download.docker.com/linux/fedora/30/x86_64/stable/Packages/containerd.io-1.2.6-3.3.fc30.x86_64.rpm
安装docker-ce yum install docker-ce
启动dockersystemctl start docker
启动成功,使用systemctl status docker 查看docker启动状态或者使用docker version验证是否安装成功。

配置镜像加速器

这里我用的是阿里云的镜像,配置加速器官方已经给到参考步骤了,如下图

常用命令

检查docker版本 docker --version or docker info
拉取镜像 docker pull <images name>
运行镜像 docker run -i -t --name <new container name> <images name>

参数说明:
 -d: 后台运行 ;
 -p: 映射端口 ;
 --name : 譬如 --name xxxooo: 为容器指定一个名称;
 -i: 打开stdin,用于和容器进行交互,通常与 -t 同时使用;
 -t: 为容器创建虚拟终端,我们就可以登录终端了通常与 -i 同时使用。

提示:使用ctrl+d 可退出当前终端。ctrl+p+q 退出容器但不关闭

列出容器 docker ps
查看到当前所有容器 docker ps -a
再次启动运行容器 先通过 docker ps -a 获得容器ID ,使用 docker start <container ID> 启动容器,使用 docker attach <container ID > 进入运行容器。当然也可以使用组合命令 docker start <contianer ID > -a -i
  -a 打开容器的输出流 -i 打开容器的输入流。注意,退出后容器也会自动停止。
在运行中的容器中执行命令进行交互式操作 docker exec -i -t <container Name or container ID > <cmd>
 docker exec -i -t myos1 /bin/bash
停止所有的container docker stop $(docker ps -a -q)
删除所有容器 docker rm $(docker ps -a -q)
删除所有镜像 docker rmi $(docker images -q)

具体命令格式规范参考官方文档

利用Dockerfile创建自定义镜像

Dockerfile是由一系列命令和参数构成的脚本,这些命令应用于基础镜像并最终创建一个新的镜像。
譬如我要用到apache,希望直接构建出一个环境容器。我们创建一个空文件夹 build,在该目录下创建一个叫做Dockerfile(注意大小写)的文件,插入内容如下:

1
2
3
4
5
FROM centos:latest
RUN yum -y install httpd
RUN systemctl enable httpd.service
CMD /usr/sbin/init # 如果这里不加cmd 的话,运行命令需要改写成 docker run --privileged -d -p 8080:80 --name myhttpd centos:httpd /usr/sbin/init
EXPOSE 80 # 暴露80端口

保存退出。
命令 docker build 用于读取Dockerfile创建镜像。使用命令 docker build -t centos:httpd .创建
  -t 指定镜像名称
创建完成,使用命令 docker run --privileged -d -p 8080:80 --name myhttpd centos:httpd 运行。

参考文档 https://docs.docker.com/engine/reference/builder/#usage

容器和主机间的数据共享
利用docker run -v
使用命令 docker run --privileged -d -p 8080:80 --name myhttpd -v /home/xugz/myweb:/var/www/html centos:httpd
在容器中设置了一个挂载点/var/www/html(即apache的默认的网站目录) ,并将主机上的 /home/xugz/myweb目录中的映射到/var/www/html下。
这时我们容器中操作该目录或在主机中操作,两者均是实时同步的

配置远程访问

我们发现docker默认连接方式为unix:///var/run/docker/sock。编辑docker文件修改服务启动运行方法,增加TCP连接配置,保存后重启Docker。再次查看发现已配置成功。具体命令如下

1
2
3
4
5
6
ps -ef | grep docker
sudo vim /usr/lib/systemd/system/docker.service
# 将原来`ExecStart=/usr/bin/dockerd`改成`ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock`
systemctl daemon-reload
systemctl restart docker
ps -ef | grep docker

Docker管理工具portainer

Docker API必须通过TCP公开,确保已经开放TCP连接2375端口
拉取镜像 docker pull portainer/portainer
运行容器 docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v /opt/portainer:/data --name mydocker portainer/portainer
运行成功后,浏览器输入虚拟机IP+9000即可进入对应可视化界面。初次进入portainer会让你先创建用户,密码不能少于八位。而后配置将Portainer连接到要管理的Docker环境。

如果在此时报错: Get http://192.168.2.156:2375/_ping: dial tcp 192.168.2.156:2375: connect: no route to host 。关闭防火墙即可解决。

github地址:https://github.com/portainer/portainer
portainer官网地址: https://portainer.readthedocs.io/en/latest/deployment.html

使用portainer创建MySQL容器

在搭建好的可视化界面中,找到App Templates选择需要的镜像,填写必要配置后点击部署。这里我安装的是MySQL。需要注意的是,创建完成后自动帮我们启动这个镜像,MySQL官方提醒使用命令docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag 进行运行需要注意。记录密码 docker run --name mysql -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123123 -d mysql。之后就可以使用本地进行来连接了。当然我们也可以使用命令行docker exec -it mysql bash 进入docker的MySQL容器。

MySQL官方镜像文档: https://hub.docker.com/_/mysql/

常见问题

普通用户运行docker命令不需要使用sudo

使用root账号,修改文件 /etc/sudoers,找到 Allow root to run any commands anywhere 位置增加普通用户。如图

在Linux系统中运行没有sudo密码的特定命令
1
2
3
4
5
6
7
8
9
10
[xugz@xugz yum.repos.d]$ docker images
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.40/images/json: dial unix /var/run/docker.sock: connect: permission denied
[xugz@xugz yum.repos.d]$ sudo docker images
[sudo] password for xugz:
REPOSITORY TAG IMAGE ID CREATED SIZE
[xugz@xugz yum.repos.d]$ id xugz
uid=1000(xugz) gid=1000(xugz) groups=1000(xugz),0(root)
[xugz@xugz yum.repos.d]$ sudo usermod -aG docker $(whoami)
[xugz@xugz yum.repos.d]$ id xugz
uid=1000(xugz) gid=1000(xugz) groups=1000(xugz),984(docker),0(root)
注销并再次登录或者使用命令 `newgrp - docker` 改变当前用户的有效群组,完成后可以使用 `docker version` 命令检查安装的Docker版本了。

docker 安装完成后测试hello-world出现问题(Unable to find image ‘hello-world:latest’ locally)

安装docker之后,测试hello-world镜像,终端卡在Unable to find image 'hello-world:latest' locally位置
docker在本地没有找到hello-world镜像,也没有从docker仓库中拉取镜像,出项这个问题的原因:是因为docker服务器再国外,我们在国内无法正常拉取镜像,所以就需要我们设置国内的镜像加速器。我这里用的是阿里云,当然其他的也可以,大家可以自己选择。Docker 官方和国内很多云服务商都提供了国内加速器服务,例如: Docker官方提供的中国镜像库https://registry.docker-cn.com

1
2
3
4
5
6
7
8
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://v2xlbv24.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

参考本篇配置镜像加速器

IPv4 forwarding is disabled. Networking will not work.

解决办法:
sudo vi /etc/sysctl.conf (Linux内核参数配置文件,可在运行时修改某些内核参数,使之永久生效)
加入net.ipv4.ip_forward=1
保存并退出后 执行sudo systemctl restart network。并且需要确保8080端口已放行 sudo iptables -A INPUT -p tcp -m tcp --dport 8080 -j ACCEPT

Failed to get D-Bus connection: Operation not permitted。

使用命令docker run -d -p 8080:80 --name myhttpd centos:httpd 运行后
报错 Failed to get D-Bus connection: Operation not permitted
使用 docker run --privileged -d -p 8080:80 --name myhttpd centos:httpd 运行解决。
 –privileged 参数,给容器加特权,否则交互式方式进入容器无法操作一些譬如修改内核、修改系统参数、甚至启动服务等

参考
https://docs.docker.com/engine/reference/commandline/run/#capture-container-id-cidfile
https://github.com/moby/moby/issues/7459
https://developers.redhat.com/blog/2014/05/05/running-systemd-within-docker-container/

使用Dockerfile成功启动Apache但浏览器拒绝访问

如果是防火墙的问题,出现的报错提示应该是无法连接之类的,一般出现404 403那说明能连上。
因为默认的容器里可能没有设置默认主页配置,所以先将apache的默认主页index.html或index.htm 在浏览器输全尝试。
若还不行,进入容器,curl http://localhost/index.html尝试,确保浏览器地址没有输错。
若还不行,进入apache配置文件 /etc/httpd/conf/httpd.conf 找到默认目录DocumentRoot然后查看 这个目录是否有,且对应文件是否存在。
我这里的问题是,安装的这个apache镜像没有默认主页,新建就可以了……

启动容器时报错Error response from daemon: driver failed programming external connectivity on endpoint mysql

docker服务启动时定义的自定义链DOCKER由于某种原因被清掉,重启docker服务及可重新生成自定义链DOCKER。使用命令systemctl restart docker在重新启动容器即可。如图

docker log 报错 SELinux: Could not open policy file <= /etc/selinux/targeted/policy/policy.31: No such file or directory

因为使用centos镜像的问题,需要处理SELinux。实际开发中使用镜像alpine,这里就先放过这个问题,以后再表。

参考地址

阿里云docker安装帮助文档
官方文档基本命令参考地址
配置镜像加速器阿里云文档
管理工具portainer仓库地址
管理工具portainer官网地址

本文标题:docker基础及常见问题

文章作者:xugz

发布时间:2019年11月21日 - 16:43

最后更新:2021年09月11日 - 16:16

原始链接:https://xlline.github.io/2019/11/21/Docker-%E5%9F%BA%E7%A1%80%E5%8F%8A%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。