vlambda博客
学习文章列表

从零开始入门docker

docker

前言

作为一个前端开发者,在工作中实际接触到docker的情况很少,但是如果个人想要搭建一个应用,又离不开docker,因此简单学习了下docker。这篇文章来自B站视频学习后的笔记,内容基础浅显,大神绕路。

docker的基本组成

docker组成大致分为三个部分:客户端,服务器以及仓库。

客户端(client)用来启动docker中的容器(container),而容器需要从仓库(registry)中进行下载。接下来我们介绍一下docker中常用的一些术语。现在可以先不是特别清楚,只需要保留一个简单的印象,随着使用的深入,才能够加深对它们的认识。

客户端(clilent):

客户端只要是运行一些docker命令,比如打包,拉取已经运行。

服务器端(server):

服务器端主要是保存docker镜像,通过镜像创建一个个的容器,每个容器就是一个或者一组应用,从而实现运行应用。

镜像(image):

镜像就好比是一个模板,可以通过这个模板来创建容器服务,比如一个tomcat镜像=>通过run运行起来 =>运行起来后就创建了一个具体的tomcat容器(比如tomcat01),这个具体的容器就是用来提供服务的。通过这个镜像可以创建多个容器,最终服务或者项目的运行都是在容器中的。

容器(container):

docker利用容器技术,独立运行一个或者一组应用,容器都是通过镜像来创建的。容器具有启动,暂停,删除等基本命令。更加通俗地来说,我们可以把容器看做是一个简易的Linux系统,应用都是运行在系统上。

仓库(repository):

仓库就是用来存放镜像的地方。仓库分为公有仓库和私有仓库。

仓库默认都是国外的,因此我们通常需要配置镜像加速(比如阿里云,华为,网易的镜像加速)。

安装docker

环境准备

  1. 阿里云服务器
  2. Linux基础

安装

安装安装的过程非常复杂,不同的环境下安装方式不同,下面给出ubuntu下安装的具体方式。按照上面的步骤进行安装即可。

https://docs.docker.com/engine/install/ubuntu/     // ubuntu下安装

查看是否安装成功

systemctl start docker    // 启动docker
docker version            // 如果出现版本信息表示安装成功

查看docker能否正常运行

docker run hello-world    // 表示创建一个helloworld镜像

查看hello-world镜像是否安装成功

docker images    // 查看所有镜像
REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
hello-world            latest              bf756fb1ae65        7 months ago        13.3kB

卸载docker

apt-get purge docker-ce docker-ce-cli containerd.io    // Ubuntu  删除软件
rm -rf /var/lib/docker    // 删除目录    /var/lib/docker是docker的默认工作路径

阿里云镜像加速

  1. 登录阿里云搜索容器镜像服务
  2. 找到镜像中心的镜像服务器
  3. 需要一步一步地完成下面的四步操作。
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://s360h258.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

docker run 运行过程

docker run xxx会运行一个镜像,这个过程究竟是怎样的?

从零开始入门docker

从上面的过程中我们可以看到,当运行docker run hello-world时,docker会首先从本地进行查找,看本地是否已经存在hello-world镜像,如果本地有,那么就直接使用本地镜像进行运行。如果本地没有这个镜像,那么会从docker hub(类似于github)进行下载,如果docker hub存在该镜像,那么可以进行下载到本地并运行,如果docker hub没有该镜像,那么会报错,提示找不到该镜像。这就是整个的docker run 的过程。

docker的底层原理

docker内部是如何工作的?

docker是一个Client-Server的结构,Docker的守护进程运行在主机上,通过Socket从客户端访问。Docker-Server接收到Docker-Client的指令,守护进程就会执行这些命令。这些命令都是用于操作docker上的容器或者说镜像,所有的容器和镜像都是通过守护进程去进行操作。没有接收到lcient的命令,这些容器不会执行。

docker为什么比VM快?


  1. docker有着比虚拟机更少的抽象层。
  2. docker利用的是宿主机的内核,而VM需要搭建一个新的Guest OS

所以说,新建一个容器的时候,docker不需要像虚拟机一样重新加载一个操作系统内核,而是直接使用宿主的内核。虚拟机是每创建一个容器都需要加载一个Guest OS。

docker的常用命令

帮助命令

docker version       //  显示docker的版本信息
docker info          //  查看更详细的docker信息,包括镜像,容器信息等。
docker 命令 --help    //  帮助命令
https://docs.docker.com/reference/

镜像命令

**docker images:**查看所有本地的主机上的镜像

root@haiying:~# docker images
REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
haiying/node-web-app   latest              51d94dc7db06        2 days ago          1.37GB
hello-world            latest              bf756fb1ae65        7 months ago        13.3kB
# 解释
REPOSITORY:镜像的仓库源名称
TAG:镜像的标签(版本信息)
IMAGE ID:镜像的id
CREATED:镜像创建的时间
SIZE:镜像的大小
# 可选项
root@haiying:~# docker images --help
Usage:  docker images [OPTIONS] [REPOSITORY[:TAG]]
List images
Options:
  -a, --all             # 列出所有的镜像
  -q, --quiet           # 只显示镜像的ID 
  

**docker search:**搜索镜像

root@haiying:~# docker search mysql
NAME       DESCRIPTION                                     STARS              OFFICIAL            
mysql      MySQL is a widely used, open-source relation…   9827                OK

docker pull:下载镜像

# docker pull + 镜像名称a:tag
docker pull mysql 

docker rmi:删除镜像

# docker rmi -f + 镜像id或者镜像名称  删除一个镜像
# docker images 通常删除前和删除后都使用docker images查看镜像是否存在或者是否删除成功
root@haiying:~# docker rmi -f hello-world
Untagged: hello-world:latest
Untagged: hello-world@sha256:49a1c8800c94df04e9658809b006fd8a686cab8028d33cfba2cc049724254202
Deleted: sha256:bf756fb1ae65adf866bd8c456593cd24beb6a0a061dedf42b26a993176745f6b

容器命令

说明,我们有了镜像才能够创建容器,因此,我们可以先下载一个ubuntu来进行测试

docker pull ubuntu
root@haiying:~# docker pull ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
3ff22d22a855: Pull complete                                                                             e7cb79d19722: Pull complete                                                                             323d0d660b6a: Pull complete                                                                             b7f616834fd0: Pull complete                                                                             Digest: sha256:5d1d5407f353843ecf8b16524bc5565aa332e9e6a1297c73a92d3e754b8a636d
Status: Downloaded newer image for ubuntu:latest
docker.io/library/ubuntu:latest

新建容器并启动

docker run [potion] images  启动一个镜像
# 参数说明
--name=Name 容器名字  mysql1 mysql2 用来区分容器
-d          后台方式运行 (经常使用)
-it         进入容器,使用交互方式运行 (经常使用)
-p          指定容器端口         -p  8080:8080
    -p   主机端口:容器端口(最常用的)
    -p   容器端口
-P          随机指定端口

#
 测试
root@haiying:~# docker run -it ubuntu /bin/bash        # 进入ubuntu容器中。
root@bcadb54c13dc:/# ls       #查看容器内的ubuntu 从获取的目录可以看到,实际上这个容器就是一个小型的Linux操作系统
# 容器内的操作系统和容器外的操作系统没有关系。
bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@bcadb54c13dc:/# 
# 从容器中退回主机
root@bcadb54c13dc:/# exit
exit
root@haiying:~#  

列出所有运行容器的命令

root@haiying:~# docker ps       # 列出当前正在运行的容器    
# 参数
        列出当前正在运行的容器
-a      列出所有运行过的容器(历史记录)
-n=2    列出最近运行的2个容器 

退出容器

exist         # 退出容器同时停止容器
ctrl + P +Q   # 不停止容器进行退出

删除容器

docker kill + 容器id  # 关闭正在运行的容器  
docker rm + 容器id    # docker rm不能删除正在运行的容器。如果想要强制删除使用rm -f

启动和停止容器

docker start + 容器id       # 启动一个容器
docker restart + 容器id     # 重启一个容器  通常我们可以通过docker ps -a 获取历史容器id,然后使用restart重启
docker stop + 容器id        # 停止一个容器
docker kill + 容器id        # 杀死一个容器

常用的其他命令

后台启动容器

通常情况下我们都是通过docker run -it 的方式(即进入容器的方式进行启动),但是我们也可以直接通过后台启动容器,而不进入容器。

# docker run -d + 镜像名  来后台启动容器
root@haiying:~# docker run -d ubuntu
88e36488d4386915d59c2f90c55b767dee456e5a354665206caec16052949840
root@haiying:~# docker ps
# 问题:通过后台启动的方式,会发现docker ps查询时启动的容器被关闭了
# 常见的坑,docker 容器通过后台启动运行,那么就必须要有一个前台进程。docker发现没有应用,那么就会自动停止。
# 以nginx为例,容器启动后,发现自己没有提供服务,就会立刻停止。

查看日志

docker logs -tf --tail 10 + 容器ID      # 查看10条日志
# 参数说明
--tail   要显示的条数
-tf   -t 表示时间戳  -f 表示输出日志

查看容器中进程信息

# docker top +容器ID 查看容器内进程信息

root@haiying:~# docker top 2c45
UID    PID     PPID     C    STIME     TTY  TIME             CMD
root   11347    11323    0    Aug09    ?    00:00:27       node /opt/yarn-v1.22.4/bin/yarn.js start
root   11399    11347   0     Aug09    ?    00:00:00       /bin/sh -c next start

查看镜像的元数据

# docker inspect + 容器ID  查看容器的元数据
root@haiying:~# docker inspect 2c45
[
    {
        "Id": "2c4526365f9577977a52e18b7e5e8a42c4864cbd1592641a45173655a80f5cfa",
        "Created": "2020-08-09T13:21:05.151305142Z",
        "Path": "docker-entrypoint.sh",
        "Args": [
            "yarn",
            "start"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 11347,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2020-08-09T13:21:05.53921525Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        # ...
        "Image": "sha256:51d94dc7db06d463c72019aec30c01b465008e516baf7b05fe7e192cb8e90f28",
        "Name": "/app",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "Config": {},
        "NetworkSettings": {
            "Networks": {
                "host": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "514dd57752f83059ae85f1a69d08cd236a05dad42f96f66d179d414f9c951342",
                    "EndpointID": "5b8e5ebde47973c0ab0d0980e3da8c6155d54f06aaeaf37e78b1c2b926d3a82c",
                    "Gateway": "",
                    "IPAddress": "",
                    "IPPrefixLen": 0,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "",
                    "DriverOpts": null
                }
            }
        }
    }
]

进入当前正在运行的容器

# 容器都是通过后台方式运行的,这时候如果我们需要修改一些容器配置,那么久需要进入容器。
# 命令
docker exec -it +容器ID + bash默认的命令行  # -it 以交互的方式进入

从容器内拷贝数据

数据都保存在docker容器中,只要容器没有被杀掉(无论容器是否处于运行开启状态),那么数据就不会丢失。但是有时候为了防止数据丢失,我们需要把数据从容器内拷贝到服务器上。

# docker cp  容器ID:数据地址    服务器上地址
docker cp 23a4:/home/test /home
ps:这里的拷贝是一个手动的过程,实际上我们还可以通过-v 卷的技术可以实现自动同步

实践

使用docker 部署一个nginx

1. docker search nginx     # 查找nginx  或者从docker hub中查找具体的详细
2. docker pull nginx       # 下载nginx
3. docker images           # 查看镜像是否下载成功
4. docker run -d --name nginx01  -p 3000:80 nginx   # 使用后台方式启动nginx 同时给nginx命名为nginx1 同时将服务器的3000端口映射到nginx的80端口,这样的话外界就可以通过3000端口来访问nginx了。
5. docker ps               # 查看nginx01容器是否启动
   #  或者  curl localhost:3000   或者
6. 阿里云服务器IP:3300    # 在浏览器中访问,查看是否出现nginx的欢迎页面
7. docker exec -it nginx01 bash   # 进入nginx 如果想要进行配置信息的设置,必须进入容器
8. whereis nginx            # 查看nginx

总结

本文主要介绍了以下内容:

  1. docker的基本组成以及常见的术语

  2. docker的安装以及一些跟安装相关的命令

  3. 介绍了docker 的一些关键原理。docker run 是如何工作的,docker的运行原理,docker为什么比虚拟机快?

  4. 介绍了docker的一些核心命令,包括:镜像命令,容器命令以及其他的一些命令,比如日志命令等。

  5. 使用docker部署了一个nginx应用进行了实践。

通过以上的学习,我们能够掌握一些docker的基础知识,能够在使用时知道如何去查找资料,如何查看问题。更多的关于docker的知识,需要更加深入的学习。

参考文章及视频

docker官方文档

docker中文社区

docker hub

dicker最新超详细教程B站