Docker安装以及常用Docker命令详解

本安装过程参考官网步骤,对每一步过程添加了注释,并进行了部分精简,有需要的小伙伴可以去官网 https://docs.docker.com/engine/install/ubuntu/ 查看更详细的安装步骤,这里以Ubuntu为例进行Docker安装。

一、安装Docker

# 以root用户登录,输入依次执行下面的命令,否则需要加sudo
# 更新软件源
apt-get update
# 所需依赖
apt-get -y install apt-transport-https ca-certificates curl software-properties-common
# 安装 GPG证书
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
# 新增阿里云软件源,为下载docker安装包提速
add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
# 再次更新软件源
apt-get -y update
# 安装Docker CE版
apt-get -y install docker-ce docker-ce-cli containerd.io

# 测试Docker是否安装成功
# 等待安装完成,通过运行hello-world映像验证Docker引擎安装是否正确
docker run hello-world

二、配置Docker加速器

Docker安装完成后,国内使用Docker去下载一些应用的镜像速度特别慢,所以这时需要给Docker配置加速器,类似于给Ubuntu的apt修改软件源,Docker也可以改镜像源。将下面的命令复制到命令行执行即可:

tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://43h8ayp0.mirror.aliyuncs.com"]
}
EOF

上面的命令会在 /etc/docker目录下创建daemon.json文件,文件中写入加速链接的地址。

注:Ubuntu 16.04+、Debian 8+、CentOS 7+

对于使用 systemd(Ubuntu 16.04+、Debian 8+、CentOS 7) 的系统,请在 /etc/docker/daemon.json 中写入如下内容(如果文件不存在请新建该文件)

https://registry.docker-cn.com这个中国的加速网站已经不行了,速度非常慢,建议改成阿里的源加速https://43h8ayp0.mirror.aliyuncs.com,这个加速网站可以自己登陆阿里云控制台,搜索容器镜像服务,每个用户都可以免费获取属于自己的加速链接。

阿里云Docker镜像加速器

//重启docker
systemctl daemon-reload
systemctl restart docker

修改完之后检查加速器是否生效,输入

docker info  //打印docker的相关信息

如果在列出的docker信息里面找到配置好的加速器,就说明配置生效了,下面就使用docker可以安装应用了

docker配置加速器以后查看配置是否生效

三、Docker常用命令介绍

1. Docker镜像操作

(1)获取镜像

从 Docker 镜像仓库获取镜像的命令是 docker pull。其命令格式为:

docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]

具体的选项可以通过 docker pull --help 命令看到,这里我们说一下镜像名称的格式。

  • Docker 镜像仓库地址:地址的格式一般是 <域名/IP>[:端口号]。默认地址是 Docker Hub。
  • 仓库名:如之前所说,这里的仓库名是两段式名称,即 <用户名>/<软件名>。对于 Docker Hub,如果不给出用户名,则默认为 library,也就是官方镜像。

下载镜像之前可以先访问docker的官方仓库网站:https://hub.docker.com/,在搜索框中输入你想下载的镜像,然后浏览一下,看看你需要什么版本的镜像,降版本号复制下来,如果对版本没有要求,可以用默认的版本(latest)。例如,你想下载ubuntu 16.04版本的镜像,可以使用如下命令:

docker pull ubuntu:16.04

(2)运行镜像

有了镜像后,我们就能够以这个镜像为基础启动并运行一个容器。例如运行下载好的Ubuntu镜像,并且我想在进入这个Ubuntu系统,操作它的终端,命令如下:

docker run -it --rm ubuntu:16.04 bash

如果想退出操作界面,可以输入exit退出,或者使用快捷键:CTRL+D

docker run 就是运行容器的命令,这里简要的说明一下上面用到的参数。

  • -it:这是两个参数,一个是 -i:交互式操作,一个是 -t 终端。我们这里打算进入 bash 执行一些命令并查看返回结果,因此我们需要交互式终端。

  • –rm:这个参数是说容器退出后随之将其删除。默认情况下,为了排障需求,退出的容器并不会立即删除,除非手动 docker rm。我们这里只是随便执行个命令,看看结果,不需要排障和保留结果,因此使用 --rm 可以避免浪费空间。

  • ubuntu:16.04:这是指用 ubuntu:16.04 镜像为基础来启动容器。

  • bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 bash。

我们一般启动的服务更常见于放在后台运行,所以可以加上 -d参数。

例如我们想在后台启动tomcat,就可以用下面的命令

docker run -p 80:8080 -d tomcat

其中

  • -p 80:8080:将docker容器的8080端口映射到宿主机的80端口

  • -d:应用在后台运行

(3)镜像的查看和删除

查看:

以列表形式查看已经下载好的镜像的详细信息

docker image ls

或者可以简写为

docker images
删除

如果要删除本地的镜像,可以使用docker image rm命令,其格式为:

docker image rm [选项] <镜像1> [<镜像2> ...]

或者可以简写为

例如删除镜像ubuntu:16.04,可以使用如下命令:

docker rmi ubuntu:16.04 或者 docker rmi 74f8760a2a8b

其中74f8760a2a8b是IMAGE ID

(4)虚悬镜像的产生和删除

有时候使用pull命令更新了镜像,比如上面举例中的Ubuntu 16.04的镜像官方发布了更新。而你的docker中的Ubuntu是在更新之前的版本,通过使用下面的命令,会更新本地的镜像。

docker pull ubuntu:16.04
  • 这个时候使用docker images或者docker image ls查看系统镜像信息的时候会出现REPOSITORY(仓库名)和TAG(标签名)值都为的情况,这是由于新旧镜像同名,旧镜像名称会被取消,从而出现仓库名和标签名都为的情况,这类镜像成为虚悬镜像

  • 使用build命令也可能产生虚悬镜像。

  • 一般来说,虚悬镜像已经失去了存在的意义,是可以随意删除的,使用下面的命令删除:

    docker image prune
    

(5)查看镜像、容器、数据卷锁占用的空间

docker system df

2. Docker容器操作

(1)查看容器的详细信息

查看后台运行的容器

docker ps

查看所有的容器信息,包括已经停止运行的容器

docker ps -a

容器和镜像的区别:镜像和容器的关系就好比Java中的类和对象,可以通过镜像构建出多个容器,这些容器之间相互独立,这得益于Docker的沙箱机制。

(2)删除某个容器,后面可以跟多个容器ID

docker rm 容器ID或容器名称

(3)停止正在运行的容器,后面可以跟多个容器ID

docker stop 容器ID或容器名称

(4)启动已经停止的容器,后面可以跟多个容器ID

docker start 容器ID或容器名称

(5)批量删除容器

如果有多个容器都停止了,我们想把停止的容器都删除了,但是又不想一个一个删除,可以使用下面的命令进行批量删除

docker container prune

3. 使用Dockerfile构建自定义镜像

(1)区别两条命令:

docker run -it tomcat bash

这个指令会以沙箱启动的方式运行镜像,然后用户可以在交互式终端进行文件的增删改查操作,但退出后,用户所做的修改操作都不会生效。

docker exec -it 运行的tomcat容器ID bash

这个指令会以交互的方式进入某个正在运行的容器中,这样对容器中的文件进行的修改操作,只会在该容器中生效,但是在容器关闭后,下次启动镜像,一样不会生效。

以上两条指令都不能将修改后的结果进行真正的保存,因此需要修改镜像内容。

以交互方式进入容器以后可以通过按 Ctrl+D退出

(2)Dockerfile语法介绍

先创建一个Dockerfile脚本,然后在脚本中添加构建镜像的内容。

先了解以下三条脚本语法:

  • FROM:第一行必须是 FROM + 基于的镜像名称

  • RUN:可以出现在后面的每一行, RUN + 要执行的Linux命令。

  • WORKDIR:使用WORKDIR + 目录,可以切换镜像的工作目录,这样下次启动镜像的时候,就可以直接进入这个目录了。

  • CMD:用于运行Shell脚本,只允许使用一次,如果使用了多次只有最后一次生效,例如:

    CMD ./startup.sh
    
  • ENTRYPOINT:当CMD已经使用过了,还想再执行一次Shell脚本的时候,可以使用它,不过也只能使用一次,例如:

    ENTRYPOINT ./startup.sh
    
  • 如果想要执行的Shell脚本数量超过2个时,可以重新编写一个脚本,将这三个脚本合并到一个脚本中,然后再用CMD或者

    ENTRYPOINT执行。
    

ENTRYPOINT a.sh //执行a.sh脚本 //a.sh中的内容是: ./startup.sh systemctl start mysql systemctl start nginx

  • ENV:可以定义环境变量,然后在整个Docker容器中就都可以使用了,例如:

    ENV MYSQL_VERSION 5.7.22
    
  • EXPOSE:向外暴露容器的端口,例如同时暴露8080和3306端口

    EXPOSE 8080 3306
    
例1:

我的tomcat:latest版本的镜像webapps目录为空,所以我启动tomcat镜像后,访问tomcat主页的时候报404。

docker tomcat8.5 404问题

为了解决这个问题,我执行如下指令:

docker run -it tomcat bash

然后进入了docker容器的tomcat目录下,进行了原因的探究

进入tomcat8.5容器内部

发现tomcat的webapps里面是空的,而tomcat的目录下多了个webapps.dist目录,tomcat的主页文件都在这个文件夹里面。这个bug估计是Docker团队在维护这个tomcat镜像的时候忘了改名字了。问题很清楚了,只需要把webapp.dist文件下面的内容复制或者移动到webapps目录下即可,这里我是复制的。

接着上面的镜像的构建,我新建了目录/usr/local/docker/tomcat,在这个目录下面创建Dockerfile脚本文件:

vim Dockerfile

然后在Dockerfile文件中加入下面的内容:

FROM tomcat RUN cp -r /usr/local/tomcat/webapps.dist/* /usr/local/tomcat/webapps/

保存并退出,接下来构建这个镜像,使用docker build命令, candytomcat是镜像的名称,.是当前目录(因为Dockerfile脚本文件在当前目录下)。这里的镜像名称必须小写,否则会报错。

docker build -t candytomcat .

构建完会提示构建成功,输入docker images,查看所有的镜像,即可看到刚才我自己构建好的candytomcat镜像

docker image构建过程

启动这个镜像,访问tomcat主页,能正常显示,所以构建镜像就成功了。

docker tomcat8.5启动后404问题解决

例2:

构建Docker镜像的时候把项目的压缩包部署到docker下的tomcat的ROOT目录下

创建出/usr/local/docker/CandyBlog/目录,然后进入这个目录

make dir -p /usr/local/docker/CandyBlog/
cd /usr/local/docker/CandyBlog/

编写一个index.jsp页面,模拟博客项目的首页,这里只是试验功能,所以一切从简!

vim index.jsp

在index.jsp页面中加入下面的内容:

Hello Docker

将index.jsp添加到压缩包CandyBlog.tar.gz中

tar -zcvf CandyBlog.tar.gz index.jsp

删除当前目录下的index.jsp

rm index.jsp

创建Dockerfile脚本文件:

vim Dockerfile

在Dockerfile文件中加入下面的内容:

FROM tomcat 
# 执行删除命令 
RUN rm -rf /user/local/tomcat/webapps/ROOT/* 
# 将要含有项目文件的压缩包复制到tomcat的ROOT目录下 
COPY CandyBlog.tar.gz /usr/local/tomcat/webapps/ROOT 
# 指定工作目录 
WORKDIR /usr/local/tomcat/webapps/ROOT 
# 解压并删除 
RUN tar -zxvf CandyBlog.tar.gz \    && rm CandyBlog.tar.gz # 暴露8080端口 EXPOSE 8080

执行构建命令,等待构建完毕

docker build -t candyblog .

启动构建好的candyblog镜像

docker run -p 80:8080 -d candyblog

最后去浏览器中验证即可。

(3)Dockerfile的上下文路径

docker build -t candytomcat .

其中的“.”表示Dockerfile的上下文路径:Docker在构建镜像的时候,会将当前目录下的所有文件 打包传输给Docker server,再由Docker Server解包,然后在解包后的路径下找Dockfile,解析Dockerfile文件中的内容,这一步很多人会误解,所以推荐在使用docker构建命令的时候先cd回到要构建的文件夹的最上层,然后再将当前路径,也就是“.”作为构建路径的上下文。

(4)构建一个已经存在的镜像,会产生虚悬镜像

当我们重新构建一个镜像,跟其他镜像同名,如果构建成功,同名镜像会变成虚悬镜像;如果构建失败,该镜像会变成虚悬镜像。

例如:上面我自己自定义的candytomcat已经可以使用了,这次我又构建了一个同名的candytomcat,先修改刚才的Dockfile脚本,然后在脚本中添加三行内容:

  • 将工作目录切换到 /usr/local/tomcat/webapps/
  • 在webapps目录下创建一个文件夹demo1
  • 然后在demo1目录下创建一个hello.html文件

如图所示:

dockerfile workdir语法介绍

构建成功,然后再查看现有的镜像,可以看到多了一个虚悬镜像。

虚悬镜像

使用 docker image prune,删除虚悬镜像。

5、数据卷

容器的因为它的进程隔离机制使得它很安全,不会影响其他进程的运行,但是这样的话数据也被隔离了,容器一旦停止了,容器中的数据也就丢失了,在运行期间产生的数据往往是需要保存的,所以Docker中引入了数据卷。

为了将docker容器内应用的产生的数据持久化,需要将docker容器中的虚拟目录映射到宿主机的目录。这就类似于VMWare中创建的虚拟机可以开辟出跟宿主机之间的共享目录,将虚拟机中产生的数据存到宿主机上,宿主机也可以通过这个共享目录将内容写入虚拟机中。