Docker

Docker

简介:

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。

Docker 使用客户端-服务器 (C/S) 架构模式 使用远程API来管理和创建Docker容器。Docker 容器(Container)通过 Docker 镜像(Image)来创建,二者之间的关系类似于面向对象编程中的对象与类

组成:

那Docker由什么组成呢, 包括三个基本概念:

  • 仓库(Repository)
  • 镜像(Image)
  • 容器(Container)

容器:

一种虚拟化的方案(一种虚拟技术区别于传统的虚拟机)

操作系统级别的虚拟化

只能运行在相同或相似内核的操作系统

依赖于Linux内核特性:Namespace和Cgroups(ControlGroup)---缺点

在这里插入图片描述

安装

在 Linux 上安装 Docker
我的linux系统是阿里云服务器,是centos 7版本的。

前置条件
64-bit 系统
kernel 3.10+
用uname -r命令检查内核版本,返回的值大于3.10即可。

在这里插入图片描述

  • 卸载旧程序
  $ sudo yum remove docker \
         docker-client \
         docker-client-latest \
         docker-common \
         docker-latest \
         docker-latest-logrotate \
         docker-logrotate \
         docker-engine
  • 安装Docker
$ sudo yum install docker
  • 启动Docker
$ sudo systemctl start docker
  • 测试:通过运行hello-world 映像来验证是否正确安装了Docker Engine 。
    $ sudo docker run hello-world

[root@VM_0_2_centos /]# docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Already exists 
Digest: sha256:6a65f928fb91fcfbc963f7aa6d57c8eeb426ad9a20c7ee045538ef34847f44f1
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

[root@VM_0_2_centos /]# 

  • 用docker version命令查看docker版本
[root@VM_0_2_centos /]# docker version
Client: Docker Engine - Community
 Version:           19.03.9
 API version:       1.40
 Go version:        go1.13.10
 Git commit:        9d988398e7
 Built:             Fri May 15 00:25:27 2020
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.9
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.13.10
  Git commit:       9d988398e7
  Built:            Fri May 15 00:24:05 2020
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.2.13
  GitCommit:        7ad184331fa3e55e52b890ea95e65ba581ae3429
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683
[root@VM_0_2_centos /]# 

  • docker info查看docker存储位置在这里插入图片描述
  • Docker 配置加速器
    这里使用的是阿里云的镜像加速器
    在这里插入图片描述

Docker 镜像命令操作

以 NGINX 为例,镜像名后跟随版本号,不然默认下载最新版本

  • 搜索镜像
    docker search nginx
[root@lucky ~]# docker search nginx
NAME                               DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
nginx                              Official build of Nginx.                        13255               [OK]                
jwilder/nginx-proxy                Automated Nginx reverse proxy for docker con…   1812                                    [OK]
richarvey/nginx-php-fpm            Container running Nginx + PHP-FPM capable of…   775                                     [OK]
linuxserver/nginx                  An Nginx container, brought to you by LinuxS…   113                                     

  • 下载镜像
    docker pull nginx
[root@VM_0_2_centos /]# docker pull nginx:1.17.10
1.17.10: Pulling from library/nginx
afb6ec6fdc1c: Pull complete 
b90c53a0b692: Pull complete 
11fa52a0fdc0: Pull complete 
Digest: sha256:30dfa439718a17baafefadf16c5e7c9d0a1cde97b4fd84f63b69e13513be7097
Status: Downloaded newer image for nginx:1.17.10
docker.io/library/nginx:1.17.10
  • 查询所有镜像
    docker images
[root@VM_0_2_centos /]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               1.17.10             9beeba249f3e        13 days ago         127MB
centos              latest              470671670cac        4 months ago        237MB
elasticsearch       latest              5acf0e8da90b        20 months ago       486MB
  • 删除镜像
    docker rmi imageID/REPOSITORY(镜像ID/名称)
[root@VM_0_2_centos /]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               1.17.10             9beeba249f3e        13 days ago         127MB
centos              latest              470671670cac        4 months ago        237MB
elasticsearch       latest              5acf0e8da90b        20 months ago       486MB
[root@VM_0_2_centos /]# docker rmi 470671670cac
Untagged: centos:latest
Untagged: centos@sha256:fe8d824220415eed5477b63addf40fb06c3b049404242b31982106ac204f6700
Deleted: sha256:470671670cac686c7cf0081e0b37da2e9f4f768ddc5f6a26102ccd1c6954c1ee
Deleted: sha256:0683de2821778aa9546bf3d3e6944df779daba1582631b7ea3517bb36f9e4007
[root@VM_0_2_centos /]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               1.17.10             9beeba249f3e        13 days ago         127MB
elasticsearch       latest              5acf0e8da90b        20 months ago       486MB

  • 删除全部镜像
    docker rmi $(docker images -q)

  • 启动镜像生成容器

docker run -it nginx:1.17.10 /bin/bash

docker run是运行容器的命令,上面用到的参数意义如下:

  • 这是两个参数,一个是-i交互式操作,一个是-t终端。我们这里打算进入bash 执行一些命令并查看返回结果,因此我们需要交互式终端
  • nginx:1.17.10 :这是指用 nginx:1.17.10 镜像为基础来启动容器
  • /bin/bash:docker后台必须运行一个进程,否则容器就会退出,在这里表示启动容器后启动bash。

进入容器后,我们可以通过shell执行任何所需要的命令,最后我们通过exit退出这个容器。

也可通过 Ctrl + p + q 退出容器

Docker 容器操作命令

  • 查看所有正在运行的容器
    docker ps
[root@VM_0_2_centos /]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
6d222ff9b93c        nginx:1.17.10       "/bin/bash"         4 minutes ago       Up 4 minutes        80/tcp              mystifying_golick
  • 停止运行的容器
    docker stop image ID(容器ID)
[root@VM_0_2_centos /]# docker stop 6d222ff9b93c
6d222ff9b93c
  • 停止运行所有可查询到的容器
    docker stop $(docker ps -aq)

  • 查询所有停止运行的容器
    docker ps -a

[root@VM_0_2_centos /]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
6d222ff9b93c        nginx:1.17.10       "/bin/bash"         6 minutes ago       Exited (0) 39 seconds ago                       mystifying_golick
1448e803cc3f        bf756fb1ae65        "/hello"            54 minutes ago      Exited (0) 54 minutes ago                       modest_elgamal
dc6d937ffd4b        bf756fb1ae65        "/hello"            56 minutes ago      Exited (0) 56 minutes ago                       zealous_neumann
4afbf37a3765        bf756fb1ae65        "/hello"            57 minutes ago      Exited (0) 57 minutes ago                       zen_solomon
  • 启动已停止的容器
    docker start imageID(容器ID)
[root@VM_0_2_centos /]# docker start 6d222ff9b93c
6d222ff9b93c
[root@VM_0_2_centos /]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
6d222ff9b93c        nginx:1.17.10       "/bin/bash"         9 minutes ago       Up 3 seconds        80/tcp              mystifying_golick
  • 进入正在运行的容器
    docker attach imageID

ls : 查看当前目录下的所有 ls -l / ll 竖向查看

[root@VM_0_2_centos /]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
6d222ff9b93c        nginx:1.17.10       "/bin/bash"         24 minutes ago      Up 14 minutes       80/tcp              mystifying_golick
[root@VM_0_2_centos /]# docker attach 6d222ff9b93c
root@6d222ff9b93c:/# ls
bin  boot  dev	etc  home  lib	lib64  media  mnt  opt	proc  root  run  sbin  srv  sys  tmp  usr  var
root@6d222ff9b93c:/# ls -l
total 64
drwxr-xr-x   2 root root 4096 May 14 14:50 bin
drwxr-xr-x   2 root root 4096 May  2 16:39 boot
drwxr-xr-x   5 root root  360 May 29 12:23 dev
drwxr-xr-x   1 root root 4096 May 29 12:14 etc
drwxr-xr-x   2 root root 4096 May  2 16:39 home
drwxr-xr-x   1 root root 4096 May 15 20:15 lib
drwxr-xr-x   2 root root 4096 May 14 14:50 lib64
drwxr-xr-x   2 root root 4096 May 14 14:50 media
drwxr-xr-x   2 root root 4096 May 14 14:50 mnt
drwxr-xr-x   2 root root 4096 May 14 14:50 opt
dr-xr-xr-x 116 root root    0 May 29 12:23 proc
drwx------   1 root root 4096 May 29 12:20 root
drwxr-xr-x   3 root root 4096 May 14 14:50 run
drwxr-xr-x   2 root root 4096 May 14 14:50 sbin
drwxr-xr-x   2 root root 4096 May 14 14:50 srv
dr-xr-xr-x  13 root root    0 May 29 11:17 sys
drwxrwxrwt   1 root root 4096 May 15 20:15 tmp
drwxr-xr-x   1 root root 4096 May 14 14:50 usr
drwxr-xr-x   1 root root 4096 May 14 14:50 var
  • 删除容器
    docker rm imageID(容器ID) : 启动中的容器不能删除
[root@VM_0_2_centos /]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                         PORTS               NAMES
6d222ff9b93c        nginx:1.17.10       "/bin/bash"         13 minutes ago      Up 4 minutes                   80/tcp              mystifying_golick
1448e803cc3f        bf756fb1ae65        "/hello"            About an hour ago   Exited (0) About an hour ago                       modest_elgamal
dc6d937ffd4b        bf756fb1ae65        "/hello"            About an hour ago   Exited (0) About an hour ago                       zealous_neumann
4afbf37a3765        bf756fb1ae65        "/hello"            About an hour ago   Exited (0) About an hour ago                       zen_solomon
[root@VM_0_2_centos /]# docker rm 4afbf37a3765
4afbf37a3765
[root@VM_0_2_centos /]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                         PORTS               NAMES
6d222ff9b93c        nginx:1.17.10       "/bin/bash"         13 minutes ago      Up 4 minutes                   80/tcp              mystifying_golick
1448e803cc3f        bf756fb1ae65        "/hello"            About an hour ago   Exited (0) About an hour ago                       modest_elgamal
dc6d937ffd4b        bf756fb1ae65        "/hello"            About an hour ago   Exited (0) About an hour ago                       zealous_neumann

  • 删除所有停止运行的容器
    docker rm $(docker ps -aq)
[root@VM_0_2_centos /]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                         PORTS               NAMES
6d222ff9b93c        nginx:1.17.10       "/bin/bash"         14 minutes ago      Up 5 minutes                   80/tcp              mystifying_golick
1448e803cc3f        bf756fb1ae65        "/hello"            About an hour ago   Exited (0) About an hour ago                       modest_elgamal
dc6d937ffd4b        bf756fb1ae65        "/hello"            About an hour ago   Exited (0) About an hour ago                       zealous_neumann
[root@VM_0_2_centos /]# docker rm $(docker ps -aq)
1448e803cc3f
dc6d937ffd4b
Error response from daemon: You cannot remove a running container 6d222ff9b93c3fadd2d387e8179e4c634ca00e3494e667ce3abb5186dc3689ab. Stop the container before attempting removal or force remove
[root@VM_0_2_centos /]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
6d222ff9b93c        nginx:1.17.10       "/bin/bash"         14 minutes ago      Up 5 minutes        80/tcp              mystifying_golick

Docker数据管理

docker在容器中管理数据主要有两种方式:

  • 数据卷(Volumes)

  • 挂载主机目录(Bind mounts)

数据卷

数据卷是一个可供容器使用的特殊目录,它绕过文件系统,可以提供很多有用的特性:

  • 数据卷可以在容器之间共享和重用
  • 对数据卷的修改会立马生效
  • 对数据卷的更新,不会影响镜像
  • 卷会一直存在,直到没有容器使用

创建数据卷
docker volume create mydata(名称)

[root@VM_0_2_centos /]# docker volume create mydata
mydata
[root@VM_0_2_centos /]# docker volume ls
DRIVER              VOLUME NAME
local               7da31459c5972fcae9af9bb339c00084fcb9dad590e7c608d3d636a958fac247
local               mydata

  • 查看具体数据卷信息
    docker volume inspect mydata(名称)
[root@VM_0_2_centos /]# docker volume inspect mydata
[
    {
        "CreatedAt": "2020-05-29T20:50:34+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/mydata/_data",
        "Name": "mydata",
        "Options": {},
        "Scope": "local"
    }
]

注:Mountpoint为数据在本机存储的位置,如果磁盘存储空间不足可修改此位置

  • 列出数据卷列表
    docker volume ls
[root@VM_0_2_centos ~]# docker volume ls
DRIVER              VOLUME NAME
local               7da31459c5972fcae9af9bb339c00084fcb9dad590e7c608d3d636a958fac247
local               mydata

  • 删除指定数据卷
    docker volume rm volume_name (名称)
[root@VM_0_2_centos ~]# docker volume ls
DRIVER              VOLUME NAME
local               7da31459c5972fcae9af9bb339c00084fcb9dad590e7c608d3d636a958fac247
local               mydata
[root@VM_0_2_centos ~]# docker volume rm mydata
mydata
[root@VM_0_2_centos ~]# docker volume ls
DRIVER              VOLUME NAME
local               7da31459c5972fcae9af9bb339c00084fcb9dad590e7c608d3d636a958fac247

[root@VM_0_2_centos ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mysql               5.7                 a4fdfd462add        8 days ago          448MB
nginx               1.17.10             9beeba249f3e        2 weeks ago         127MB
centos              latest              470671670cac        4 months ago        237MB
elasticsearch       latest              5acf0e8da90b        20 months ago       486MB
[root@VM_0_2_centos ~]# docker run --name mysql01 -d -p 9100:3306 -v /home/lucky/volume-test:/home mysql:5.7
15f5f72beb3715efa92ac95e0c35ce7da9f7dbe441e352b8d2ee073be7b8fb52

使用 MySQL 5.7 版本镜像创建名为 MySQL01 的容器,
-d : 守护模式启动
-p : 暴露端口 9100(对外使用9100代替原来的3306)
将主机的 / home/lucky/volume-test 与容器中的 /home 映射
:如果没有此目录会被创建

挂载

方式一:直接使用命令来挂载

docker run -it 主机目录:容器目录

# 容器中添加 ceshi.sh 文件
[root@VM_0_2_centos lucky]# docker run -it -v /home/lucky/ceshi:/home centos /bin/bash
[root@5ec00a74380e /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@5ec00a74380e /]# cd /home
[root@5ec00a74380e home]# ls
[root@5ec00a74380e home]# touch ceshi.sh   
[root@5ec00a74380e home]# ls
ceshi.sh
[root@5ec00a74380e home]# 

使用 docker inspect 容器 id 查看挂载信息

在这里插入图片描述

# 容器中的文件同步到主机中
[root@VM_0_2_centos ~]# cd /home/lucky/ceshi
[root@VM_0_2_centos ceshi]# ls
ceshi.sh
[root@VM_0_2_centos ceshi]# 

# 在主机中修改文件信息
[root@VM_0_2_centos /]# cd /home/lucky/ceshi
[root@VM_0_2_centos ceshi]# ls
ceshi.sh
[root@VM_0_2_centos ceshi]# vim ceshi.sh
[root@VM_0_2_centos ceshi]# cat ceshi.sh
hello my first test
[root@VM_0_2_centos ceshi]# 

容器中的文件也被同步
在这里插入图片描述

# 退出容器并将容器停止运行
[root@a790e015183e home]# exit
exit
[root@VM_0_2_centos /]# docker stop a790e015183e
a790e015183e

再次将主机中文件信息修改
在这里插入图片描述

# 重新启动并进入容器中查看,文件依然被同步
[root@VM_0_2_centos /]# docker start a790e015183e
a790e015183e
[root@VM_0_2_centos /]# docker attach a790e015183e
[root@a790e015183e /]# cd /home
[root@a790e015183e home]# ls
ceshi.sh
[root@a790e015183e home]# cat ceshi.sh
hello my first test
this is second
[root@a790e015183e home]# 

# 删除容器
[root@VM_0_2_centos /]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                        PORTS               NAMES
5ec00a74380e        centos              "/bin/bash"         2 minutes ago       Exited (127) 22 seconds ago                       angry_neumann
[root@VM_0_2_centos /]# docker rm 5ec00a74380e
5ec00a74380e
[root@VM_0_2_centos /]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@VM_0_2_centos /]# 

# 主机中的文件依然存在
[root@VM_0_2_centos ceshi]# ls
ceshi.sh

方式二:
docker run --name xxxx -p 8888:8888 --mount type:volume,source=/src/xxx,target=/xxx /my:/docker -it imagename /bin/bash

type选项,其可以是bind,volume,或 tmpfs。本主题讨论卷,因此类型始终是 volume

注意:使用-v参数时如果本地目录不存在Docker会自动为你创建一个文件夹。使用–mount参数时如果本地目录不存在,Docker会报错。Docker挂载主机目录的默认权限是读写,用户也可以通过增加readonly指定为只读。

  • 如果挂载一个空的数据卷到容器中的一个非空目录中,那么这个目录下的文件会被复制到数据卷中。(我的测试:使用 -v 参数并没有这个效果,需要使–mount参数,如果不符请指正)
  • 如果挂载一个非空的数据卷到容器中的一个目录中,那么容器中的目录中会显示数据卷中的数据。如果原来容器中目录非空,那么这些原始数据会被隐藏掉。

Dockerfile

关于Dockerfile

在Docker中创建镜像最常用的方式,就是使用Dockerfile。Dockerfile是一个Docker镜像的描述文件,我们可以理解成火箭发射的A、B、C、D…的步骤。Dockerfile其内部包含了一条条的指令,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。

在这里插入图片描述

Dockerfile常用指令

在这里插入图片描述

FROM

scratch是虚拟的镜像,表示一个空白的镜像,也是最为基础的镜像。

MAINTAINER

指明镜像维护着及其联系方式(一般是邮箱地址):
lucky < xxxxxxxx@xx.com >

RUN

构建镜像时运行的Shell命令

shell 格式: RUN <命令> ,RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
exec 格式: RUN ["可执行文件", "参数1", "参数2"] 。run可以写多个,每一个指令都会建立一层,所以正确写法应该是↓
RUN buildDeps='gcc libc6-dev make' \
         && apt-get update \
         && apt-get install -y $buildDeps \
         && wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" \
         && mkdir -p /usr/src/redis \
         && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
         && make -C /usr/src/redis \
         && make -C /usr/src/redis install \
         && rm -rf /var/lib/apt/lists/* \
         && rm redis.tar.gz \
         && rm -r /usr/src/redis \
         && apt-get purge -y --auto-remove $buildDeps
ADD

拷贝文件或目录到镜像中

ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz /
<源路径> 可以是一个 URL ,下载后的文件权限自动设置为 600 。
ADD html.tar.gz /var/www/html
ADD https://xxx.com/html.tar.gz /var/www/html

PS : 如果是URL或压缩包,会自动下载或自动解压

WORKDIR

为RUN、CMD、ENTRYPOINT以及COPY和AND设置工作目录

WORKDIR <工作目录路径>
RUN cd /app
RUN echo "hello" > world.txt
两次run不在一个环境内,可以使用WORKDIR。
VOLUME

指定容器挂载点到宿主机自动生成的目录或其他容器

VOLUME ["/var/lib/mysql"]
EXPOSE

声明容器运行的服务端口

EXPOSE <端口1> [<端口2>...] 
EXPOSE :EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射。
CMD

启动容器时执行的Shell命令

shell 格式: CMD <命令>
exec 格式: CMD ["可执行文件", "参数1", "参数2"...]

CMD ["nginx", "-g", "daemon off;"]
ENV

在其他指令中可以直接引用ENV设置的环境变量。

ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
示例:
ENV VERSION=1.0 DEBUG=on NAME="Happy Feet"

案例

使用 vim dockerfile 创建并编辑文件

FROM centos

MAINTANIER www.edisonchou.com

ADD jdk-8u45-linux-x64.tar.gz /usr/local

ENV JAVA_HOME /usr/local/jdk1.8.0_45

ADD apache-tomcat-8.0.46.tar.gz /usr/local

COPY server.xml /usr/local/apache-tomcat-8.0.46/conf

RUN rm -f /usr/local/*.tar.gz

WORKDIR /usr/local/apache-tomcat-8.0.46

EXPOSE 8080

ENTRYPOINT ["./bin/catalina.sh", "run"]

CMD "----end----"

使用 docker build -f dockerfile -t lucky/mytomcat:v1(这是定义 tag 的版本号信息) 构建镜像

运行镜像生成容器
docker run -it --name mytomcat1 -p 9100:8080 -d 6d279e252e0b

进入容器查看
docker exec -it mytomcat /bin/bash

CMD和ENTRYPOINT区别

CMD 会覆盖只会执行最后一条,如果运行时有其他命令会覆盖

# 文件执行后用 ls-a 进行查询
CMD ["ls","-a"]
如
docker run -it mytomcat -l
会将 CMD 覆盖 变成 -l

ENTRYPOINT 则会在后进行追加

ENTRYPOINT ["ls","-a"]

ls -al

将镜像发布到阿里云

创建自己的镜像仓库

在这里插入图片描述

剩下按照步骤即可上传

在这里插入图片描述

入门就到这里吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值