Ubuntu上安装使用Docker

Docker简介

  • Docker是一个开源的容器引擎,他有助于更快的交付应用。Docker可以将应用程序和基础设施层做隔离,并且能将基础设施当做程序一样进行管理。使用Docker,可以更快的打包,测试以及部署应用程序,并且可以缩短从编写到部署运行的代码调试周期。
    Docker官网
    Docker 的GitHub

Docker 的架构

  • 以下是Docker官方文档的架构图
    在这里插入图片描述
  • Docker daemon(Docker守护进程):Docker daemon是一个运行在宿主机(DOCKER_HOST)的后台进程。可以通过Docker客户端与Docker daemon进行通信
  • Client (Docker 客户端): Docker客户端是Docker的用户界面,他可以接受用户命令和配置标识,并与Docker daemon通信。途中,Docker build 等都是Docker的相关命令
  • Images(Docker 的镜像):Docker镜像是一个只读的模板,他包含创建Docker容器的说明。他和系统安装光盘有点像----使用系统安装光盘可以安装系统,同理,使用Docker镜像可以运行Docker镜像中的程序。
  • Container(容器):容器是镜像的可运行实例。镜像和容器的关系有点类似面向对象中的,类之于对象的关系。可通过Docker API或者CLI命令来启动停止,移动,删除容器。
  • Registry(类似代码仓库):Docker Registry是一个集中存储于分发镜像的服务。构建完Docker镜像后,就可以在当前宿主机上运行。如果想在其他机器上运行这个镜像,需要手动负责,或者借助Docker Registry来避免负责,经Docker镜像push到Docker Registry上,然后在其他机器上pull对应镜像。

Docker安装

  • 准备Ubuntu系统,或者虚拟机,安装程序可参照网址
安装Docker
  • 官方Ubuntu存储库中提供的Docker安装包,但是可能不是最新的版本,为了确保获取最新版,我们将从Docker官网存储库安装Docker。因此,我们需要添加一个新的资源包,从Docker添加GPG以确保下载有效,然后安装该包:
  • 首先更新现有包列表,新安装的ubuntu这个步骤可能会久一点:
sudo apt update
  • 接下来使用按apt 安装一下运行通过HTTPS才能使用的软件包
sudo apt install apt-transport-https 
sudo apt install ca-certificates 
sudo apt install curl 
sudo apt install software-properties-common
  • 将官方Docker存储的GPG秘钥添加到系统:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
  • 将Docker存储库添加到APT源:
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
  • 接下来,使用新添加的repo源中的Docker包更新数据库:
sudo apt update
  • 确保从Docker repo安装,而不是默认的Ubuntu repo:
apt-cache policy docker-ce
  • 看到如下的输出,说明是成功的,版本不同输出的日志应该有一点点差异:
docker-ce:Installed: (none)Candidate: 5:19.03.12~3-0~ubuntu-bionicVersion table:5:19.03.12~3-0~ubuntu-bionic 500500 https://download.docker.com/linux/ubuntu bionic/stable amd64 Packages
  • 现在Docker-ce还没有安装,用上面这个命令我们能看到安装源来自Docker官方存储库,最后安装Docker:
sudo apt install docker-ce
  • 现在Docker已经安装好了,检查一下是否正常运行:
sudo systemctl status docker
  • 有类似如下的输出,标准状态正常:
● docker.service - Docker Application Container EngineLoaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: eActive: active (running) since Tue 2020-07-21 00:07:42 PDT; 34s agoDocs: https://docs.docker.comMain PID: 20120 (dockerd)Tasks: 8CGroup: /system.slice/docker.service└─20120 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/contai
  • Docker不仅仅提供Docker服务,还提供了Docker命令行工具或者Docker客户端。
非Sudo执行Docker命令
  • 默认情况下,Docker命令只能Root用户或者Docker组中用户运行,改用户在Docker安装过程中自动创建,如果想要不使用Sudo运行,或不在docker组中的用户运行会有错误提示信息:
docker: Cannot connect to the Docker daemon. Is the docker daemon running on this host?.
See 'docker run --help'.
  • 想要在运行docer时候不输入sudo,需要将用户添加到docker组中,首先创建docker用户组
sudo groupadd docker
  • 将用户添加到docker用户组
sudo usermod -aG docker ${USER_NAME}
  • 重启docker服务
sudo systemctl restart docker
使用Docker命令
  • 以下我都用的root用户来执行,Docker命令使用包括传递一系列docker选项和命令,后跟参数。语法格式如下:
docker [option] [command] [arguments]
  • 查询所有子命令输入 docker,有如下:
Commands:attach      Attach local standard input, output, and error streams to a running containerbuild       Build an image from a Dockerfilecommit      Create a new image from a container's changescp          Copy files/folders between a container and the local filesystemcreate      Create a new containerdiff        Inspect changes to files or directories on a container's filesystemevents      Get real time events from the serverexec        Run a command in a running containerexport      Export a container's filesystem as a tar archivehistory     Show the history of an imageimages      List imagesimport      Import the contents from a tarball to create a filesystem imageinfo        Display system-wide informationinspect     Return low-level information on Docker objectskill        Kill one or more running containersload        Load an image from a tar archive or STDINlogin       Log in to a Docker registrylogout      Log out from a Docker registrylogs        Fetch the logs of a containerpause       Pause all processes within one or more containersport        List port mappings or a specific mapping for the containerps          List containerspull        Pull an image or a repository from a registrypush        Push an image or a repository to a registryrename      Rename a containerrestart     Restart one or more containersrm          Remove one or more containersrmi         Remove one or more imagesrun         Run a command in a new containersave        Save one or more images to a tar archive (streamed to STDOUT by default)search      Search the Docker Hub for imagesstart       Start one or more stopped containersstats       Display a live stream of container(s) resource usage statisticsstop        Stop one or more running containerstag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGEtop         Display the running processes of a containerunpause     Unpause all processes within one or more containersupdate      Update configuration of one or more containersversion     Show the Docker version informationwait        Block until one or more containers stop, then print their exit codes
  • 查看有关Docker的系统信息:
docker info
  • 搜索镜像:
socker search java
  • 执行后可以看到如下表格信息
NAME                                     DESCRIPTION                                     STARS               OFFICIAL      AUTOMATED
node                                     Node.js is a JavaScript-based platform for s…   9044                [OK]                
tomcat                                   Apache Tomcat is an open source implementati…   2785                [OK]                
openjdk                                  OpenJDK is an open-source implementation of …   2347                [OK]                
java                                     Java is a concurrent, class-based, and objec…   1976                [OK]                
ghost                                    Ghost is a free and open source blogging pla…   1221                [OK]                
couchdb                                  CouchDB is a database that uses JSON for doc…   358                 [OK]                
jetty                                    Jetty provides a Web server and javax.servle…   340                 [OK]                
groovy                                   Apache Groovy is a multi-faceted language fo…   97                  [OK]                
lwieske/java-8                           Oracle Java 8 Container - Full + Slim - Base…   46                                      [OK]
nimmis/java-centos                       This is docker images of CentOS 7 with diffe…   42                                      [OK]
fabric8/java-jboss-openjdk8-jdk          Fabric8 Java Base Image (JBoss, OpenJDK 8)      28                                      [OK]
frekele/java                             docker run --rm --name java frekele/java        12                                      [OK]
fabric8/java-centos-openjdk8-jdk         Fabric8 Java Base Image (CentOS, OpenJDK 8,11                                      [OK]
blacklabelops/java                       Java Base Images.                               8                                       [OK]
..............
  • 以上表格中五列含义如下:

    • NAME:镜像仓库名称
    • DESCRIPTION:镜像仓库描述
    • STARS:镜像仓库收藏数量,标识该镜像受欢迎程度,类似GitHub的Stars
    • OFFICAL:表示是否为官方仓库,改列标记为[OK] 的镜像都是各软件官方项目组创建和维护的。由结果可知,frekele/java 这个镜像不是官方仓库。
    • AUTOMATED:表示是否是自动构建的镜像仓库
  • 下载镜像

    • 使用 docker pull 命令可以从Docker Registry上下载镜像,例如:docker pull java
    • 命令执行后,Docker会从Docker Hub上的java残酷中下载最新版本的java镜像。若镜像下载缓慢可以配置加速器(以下会讲解加速器配置)
  • 列出已有镜像,使用docker images命令可以列出已经下载的镜像。执行后有如下表格:

REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
ubuntu               latest              adafef2e596e        2 weeks ago         73.9MB
645121107/ljmadmin   myHelloWorld        bf756fb1ae65        6 months ago        13.3kB
hello-world          latest              bf756fb1ae65        6 months ago        13.3kB
  • 包括五列,分别有如下意义:
    • REPOSITORY:镜像所属的仓库名称
    • TAG:镜像标签,默认是lastest,表示最新
    • IMAGE ID:镜像ID,表示镜像唯一标识
    • CREATED:镜像创建时间
    • SIZE:镜像大小
  • 删除镜像:
docker rmi hello-world
  • 删除镜像可能遇到如下问题,原因是提示有关联的Docker容器,因为我们看到bf756fb1ae65 对应了两个容器,一个是我们自己提交的tag,通过hello-world生成的一个镜像,系统无法识别你要删除的是哪一个:
root@ljmadmin-virtual-machine:/home/ljmadmin# docker rmi bf756fb1ae65
Error response from daemon: conflict: unable to delete bf756fb1ae65 (must be forced) - image is referenced in multiple repositories
  • 我们删除的时候可以用指定repository和tag的方式来删除,比如:
root@ljmadmin-virtual-machine:/home/ljmadmin# docker rmi hello-world
Untagged: hello-world:latest
Untagged: hello-world@sha256:49a1c8800c94df04e9658809b006fd8a686cab8028d33cfba2cc049724254202
  • 如上,线上已经被删除成功
批量删除镜像
  • 删除所有:
docker rm `docker ps -a -q`
  • 删除所有镜像
docker rmi `docker images -q`
  • 按条件删除镜像
//没有标签情况
docker rmi `docker images -q | awk '/^<none>/ {pring $3}'`
//镜像名包含关键字
docker rmi --force `docker images | grep eureka | awk '{print $3}'`    //其中eureka为关键字
Docker 容器常用命令
  • 新建并启动容器:使用docker run 命令可以新建并启动一个容器。该命令是常用命令,他有很多选项,下面列举某一些选项:
    • -d选项:表示后台运行
    • -p选项:随机端口映射
    • -p选项:指定端扣映射,有以下四种格式:
      • ip:hostPort:containerPort
      • ip::containerPort
      • hostPort:containerPort
      • containerPort
    • –network选项: 指定网络模式,该选项有以下可选参数:
      • –network=bridge:默认选项,表示连接到默认的网桥
      • –network=host:容器使用宿主机网络
      • –network=container:NAME_or_ID:告诉Docker让新建的容器使用已有容器的网络配置。
      • –network=none:不配置该容器网络,用户可以自定义网络配置
  • 示例一,这样终端会打印Hello world,跟在本地执行/bin/echo ‘Hello world’ 得到一样的结果:
docker run java /bin/echo 'Hello world'
  • 示例二,启动一个Nginx容器,这里添加了两个参数,含义与命令如下所示:
docker run -d -p 91:80 nginx //没有nginx镜像时候,会先下载在启动
// -d 表示后台运行
//-p 宿主机端口:容器端口  # 开放容器端口到宿主机端口
  • 访问http://Docker宿主机IP:91,将会看到如下界面
    在这里插入图片描述

  • 进入容器,某些场景下需要进入容器中。

    • 使用docker sttach命令进入容器,弊端在于,使用此命令并不方便,当多个窗口同事attach到同一个容器时候,所有窗口都会同步显示。同样,当某个窗口发生阻塞,其他窗口也无法执行操作。命令如下
    • 使用nsenter进入容器:nsenter工具包含在util-linux2.23或者更高版本中。为了连接到容器,需要找到容器第一个进程PID,可以以下命令获取
    • 以上获取到PID后,就可以使用nsenter进入容器,完整命令如下
docker  attach b8488a2dcef8
docker inspect --format "{{.State.Pid}}" $CONTAINER_ID
nsenter --target "$PID" --mount --uts --ipc --net --pid
- 完整案例如下图:

在这里插入图片描述

配置镜像加速器
  • 国内访问Docker Hub的速度很不稳定,有时候会出现链接不上的情况。我们可以通过配置国内镜像加速器的形式来解决问题。目前,国内很多公司云服务商提供了镜像加速服务。常用镜像加速器有:阿里云加速器,DaoCloud加速器。我用的阿里云的加速器,配置如下:
  1. 注册阿里云账号,登录控制台(https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors),如下图
    在这里插入图片描述
  2. 按上图所示进行配置即可。
使用Docker镜像
  • Docker容器是从Docker进行构建的,默认情况下,Docker从Docker Hub中pull下来的这些镜像,这是一个由Docker管理的Docker镜像市场,这是Docker项目背后的公司。任何人都可以在Docker Hub上托管他们的Docker镜像,所以你只要将你的应用程序和LInux放再那边托管就可以。
  • 我们用刚才pull的hello-world镜像测试,输入:
docker run hello-world
  • 输出下面的内容说明已经成功运行
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 theexecutable that produces the output you are currently reading.4. The Docker daemon streamed that output to the Docker client, which sent itto your terminal.
..................
运行Docker容器
  • 上一步中,hello-world容器运行并发出一个测试消息后退出容器,容器可以比这更有用,是可以相互交互的,比较,类似虚拟机,只是更加有利于资源。
  • 我们用ubuntu的镜像做一个测试,通过-i, -t子命令提供了容器的交互shell访问:
docker pull ubuntu
docker run -it ubuntu
  • 执行以上两个命令就可以进入到ubuntu镜像内部,shell展示如下
root@ljmadmin-virtual-machine:/home/ljmadmin# docker run -it ubuntu 
root@b8488a2dcef8:/# 
  • 如上命令提示符中的容器ID,在此处是b8488a2dcef8,在此shell中不需要sudo,因为是用root用户身份在容器中操作,我们在此镜像中安装一个node:
apt update
apt install nodejs
node -v
  • 得到如下结果:
root@b8488a2dcef8:/# node -v
v10.19.0
  • 退出容器,直接输入exit或者Ctrl+d 退出,两种方式有如下区别
    • 对于创建的bash容器,当使用exit命令退出后,容器就自动处于退出(Exited)状态,这是因为对Docker容器来说,当运行的应用退出后,容器就没有继续运行的必要
    • 而用Ctrl退出后,容器还会在运行,他认为你只是退出了命令界面的链接状态而已
Docker容器管理
  • 使用Docker后,可能有很多非运行状态的容器,我们需要查询容器的运行状态用如下命令:
docker ps 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
b8488a2dcef8        ubuntu              "/bin/bash"         6 minutes ago       Up 6 minutes                            adoring_knuth
  • 看到如上输出,每一列的含义如下:

    • CONTAINER_ID:表示容器ID
    • IMAGE:表示镜像名称
    • COMMAND:表示启动容器时运行的命令
    • CREATED:表示容器创建时间
    • STATUS:容器运行状态,Up标识运行中,Exited表示停止
    • PORTS:容器对外的端口号
    • NAMES:表示容器名称,默认由Docker自动生成,也可以docker run 命令后面–name自行指定。
  • 查看所有容器情况使用 docker ps -a,得到所有的信息,如下:

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
b8488a2dcef8        ubuntu              "/bin/bash"         15 minutes ago      Up 15 minutes                                   adoring_knuth
43971aec0ea0        hello-world         "/hello"            26 minutes ago      Exited (0) 26 minutes ago                       dazzling_hodgkin
  • 只查看已经启动的容器:
docker ps
  • 启动已经停止的容器,使用Docker start ,后面跟上容器ID b8488a2dcef8 ,启动后status会变为up状态
  • 同样,停止容器,使用docker stop CONTAINER_ID,更容器id或者容器名称
  • 批量停止容器 docker stop 51c20c4f5a04 22c37049f352 1ac1218c1a54
  • 删除容器,当我们不需要某个容器时候,可以docker rm删除,上面内容以及讲过这个命令。
将容器中的更改提交给Docker镜像
  • 当启动Docker镜像后,可以像虚拟机一样创建,修改,删除文件。例如ubuntu镜像,我们所有更改都仅仅在镜像内部而已。我们可以通过docker rm销毁,但是会永久丢失。
  • 在ubuntu容器中安装Nodejs后,我们现在想要将这个容器作为一个新的容器,可以如下操作:
docker ps -a //找到对应ubuntu镜像id
docker commit -m "my ubuntu" -a "ljmadmin" b8488a2dcef8 ljmadmin/ubuntu-nodejs 
  • 如上commit命令,对于ljmadmin用户,使用容器id b8488a2dcef8 作为目标镜像,打包成新镜像 ljmadmin/ubuntu-nodejs ,得到如下所有images信息:
root@ljmadmin-virtual-machine:/home/ljmadmin# docker images
REPOSITORY               TAG                 IMAGE ID            CREATED              SIZE
ljmadmin/ubuntu-nodejs   latest              6e1bc5c5a996        About a minute ago   163MB
ubuntu                   latest              adafef2e596e        2 weeks ago          73.9MB
645121107/ljmadmin       myHelloWorld        bf756fb1ae65        6 months ago         13.3kB
hello-world              latest              bf756fb1ae65        6 months ago         13.3kB
  • 在如上列表中新镜像ubuntu-nodejs 是动Docker Hub的Ubuntu现有镜像中衍生出来的,镜像大小的差异可以看出有变化因此下次我们可以直接使用ubuntu-nodejs 新的镜像。
Dockerfile构建镜像
  • 待续
将Docker镜像推送到Docker存储库
  • 我们以上提到的从Docker Hub pull下来的镜像都是在我们本地,包括我们自己commit生成的也是在本地,如果需要迁移需要先将镜像推到远程仓库,我们需要 一个Docker Hub的仓库账号信息
docker login -u docker-registry-username //docker-registry-username 标识你注册docker Hub的用户名
  • 系统将提升输入Docker Hub的密码进行身份验证,然后你可以使用以下方法推送自己的镜像:
  • 第一步:获取需要推送到远端镜像的 容器ID(CONTAINER ID),此处我们用ubuntu来进行测试提交,ID是b8488a2dcef8,如下命令:
root@ljmadmin-virtual-machine:/home/ljmadmin# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                   PORTS               NAMES
b8488a2dcef8        ubuntu              "/bin/bash"         3 hours ago         Exited (0) 3 hours ago                       adoring_knuth
43971aec0ea0        hello-world         "/hello"            4 hours ago         Exited (0) 4 hours ago                       dazzling_hodgkin
  • 第二步将对应Docker容器打包成镜像:
root@ljmadmin-virtual-machine:/home/ljmadmin# docker commit -m "my first ubuntu" -a "ljmadmin" b8488a2dcef8 ljmadmin/ubuntu-nodejs
sha256:acd28a5810ec9e3ecd656fcaf58551552804f7a5663e3c201a1d3d7712621120
  • 第三步Docker Images 命令查询打包好的镜像文件,并且获取对应镜像ID:
root@ljmadmin-virtual-machine:/home/ljmadmin# docker images
REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
ljmadmin/ubuntu-nodejs   latest              acd28a5810ec        20 seconds ago      163MB
ubuntu                   latest              adafef2e596e        2 weeks ago         73.9MB
hello-world              latest              bf756fb1ae65        6 months ago        13.3kB
  • 第四部:将需要提交的镜像文件通过docker tag命令打包成自己仓库对应的镜像文件(之前的镜像默认是Docker hub公共的仓库)
root@ljmadmin-virtual-machine:/home/ljmadmin# docker tag acd28a5810ec 645121107/ljmadmin
root@ljmadmin-virtual-machine:/home/ljmadmin# docker images
REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
645121107/ljmadmin       latest              acd28a5810ec        15 minutes ago      163MB
ljmadmin/ubuntu-nodejs   latest              acd28a5810ec        15 minutes ago      163MB
ubuntu                   latest              adafef2e596e        2 weeks ago         73.9MB
645121107/ljmadmin       myHelloWorld        bf756fb1ae65        6 months ago        13.3kB
hello-world              latest              bf756fb1ae65        6 months ago        13.3kB
  • 此处没有指定tag的名称,如需指定名称用以下命令:
docker tag acd28a5810ec 645121107/ljmadmin:yourTagName
  • 如上images命令后可以看的多了一个仓库名称(REPOSITORY)是645121107/ljmadmin的镜像文件,并且该镜像文件的id和我们之前通过tag打包成镜像的id是同一个,说明他们是同一个文件,我们可以理解为将他的副本映射到了我们自己的仓库地址,以下是我创建的仓库
    在这里插入图片描述

  • 第五步提交对应镜像文件,通过docker push命令提交

root@ljmadmin-virtual-machine:/home/ljmadmin# docker push 645121107/ljmadmin
  • 执行以上命令后会得到如下的输出,因为文件有十几M甚至100M,所以需要一定时间,以上命令和git push类似,645121107/ljmadmin 其实就是远程仓库地址,如果ljmadmin 是别在包例如645121107/1234,docker hub也会自动在远程仓库创建新的文件1234.
    在这里插入图片描述
  • 在仓库中可以看到刚才提交的文件如下:
    在这里插入图片描述
  • 第六部:验证提交的镜像文件有效
docker rmi docker rmi 645121107/ljmadmin:latest //通过rmi命令删除本地对应的镜像文件
root@ljmadmin-virtual-machine:/home/ljmadmin# docker images  //查看现有镜像文件
REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
ubuntu               latest              adafef2e596e        2 weeks ago         73.9MB
root@ljmadmin-virtual-machine:/home/ljmadmin# docker pull 645121107/ljmadmin:latest
  • 如下图所示,说明以及在下载文件:
    在这里插入图片描述
查看Docker容器启动日志
  • 用的最多的一个,实时日志跟踪,类似 tail -f -n 300 xxx.log
sudo docker logs -f -t --tail 行数 容器名
//docker logs [OPTIONS] CONTAINER
//sudo docker logs -f -t 300 CONTAINER_ID
  • Options操作如下:

    • –details 显示更多信息
    • -f, --follow 跟踪实时日志信息
    • –since string 显示自某个timestamp之后的日志,或相对时间,如40m(40分钟)
    • -tail string 从日志末尾开始算显示多少行日志,默认是all
    • -t, --timestamp 显示时间搓
    • –until string 显示自某个timestamp之前的日志信息,或者相对时间,如40m(40分钟)
  • 查看最近30分钟的日志:

docker logs --since 30m CONTAINER_ID
  • 查看某时间之后的日志:
docker logs -f --since = "2020-08-26T13:23:37" CONTAINER_ID
  • 查看某时间段日志:
docker logs -t --since= "2020-08-25T13:23:37" --until  "2020-08-26T13:23:37" CONTAINER_ID

下一篇 SpringCloud + Docker

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/310547.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

让 .NET 轻松构建中间件模式代码

让 .NET 轻松构建中间件模式代码Intro在 asp.net core 中中间件的设计令人叹为观止&#xff0c;如此高大上的设计何不集成到自己的代码里呢。于是就有了封装了一个简单通用的中间件模板的想法&#xff0c;以后有需要的时候就可以拿来即用。接口定义这里按执行的委托是同步还是异…

[剑指offer]面试题23:从上往下打印二叉树

面试题23&#xff1a;从上往下打印二叉树 题目&#xff1a;从上往下打印出二叉树的每个结点&#xff0c;同一层的结点按照从左到右的顺序打印。例如输入图4.5中的二叉树&#xff0c;则依次打印出8、6、10、5、7、9、11。 二叉树结点的定义如下&#xff1a; struct BinaryTree…

[剑指offer]面试题26:复杂链表的复制

面试题26&#xff1a;复杂链表的复制 题目&#xff1a;请实现函数ComplexListNodeClone&#xff08;ComplexListNodepHead&#xff09;&#xff0c;复制一个复杂链表。在复杂链表中&#xff0c;每个结点除了有一个m_pNext指针指向下一个结点外&#xff0c;还有一个m_pSibling 指…

SpringCloud + Docker

Dockerfile构建Docker 镜像 注意这里说的Dockerfile是指的一个文本文件&#xff0c;类似txt&#xff0c;只不过名字是Dockerfile&#xff0c;里面编辑Docker的一些指令&#xff0c;指令作用在于描述构建镜像的细节。如下一个简单的案例&#xff0c;用上一节中下载的nginx镜像来…

从编码层面对比java和c#

java和c#都是面向对象编程高级语言&#xff0c;总体上来讲&#xff0c;它们还是很相似的&#xff0c;因为它们在发展过程中都很大程序上学习了对方不少优秀的特性。所以&#xff0c;一般来说&#xff0c;从其中一门语言转换到另外一门语言应该都不会有很大问题。虽然说这两门语…

[剑指offer]面试题28:字符串的排列

面试题28&#xff1a;字符串的排列 题目&#xff1a;输入一个字符串&#xff0c;打印出该字符串中字符的所有排列。例如输入字符串abc&#xff0c;则打印出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。 思路: 这是一个典型的递归问题&#xff0c;考虑…

红帽借“订阅”模式成开源一哥,首创者升任总裁

4 月 6 日&#xff0c;红帽公司宣布&#xff0c;产品和技术总裁 Paul Cormier 即日起任红帽总裁&#xff0c;并兼任首席执行官。Paul Cormier 是开源商业化“订阅”模式的提出者&#xff0c;这一模式促使红帽达成连续超70个季度的盈利&#xff0c;身价升至340亿美金&#xff0c…

Docker中数据管理

Docker数据管理 生产环境中&#xff0c;对数据进行持久化&#xff0c;或者需要在多个容器直接进行数据共享&#xff0c;这必然涉及到容器的一些数据管理的操作。容器中数据管理主要有两种方式&#xff1a; 数据卷&#xff08;Data Volumes&#xff09;&#xff1a;容器内数据直…

[剑指offer]面试题31:连续子数组的最大和

面试题31&#xff1a;连续子数组的最大和 题目&#xff1a;输入一个整型数组&#xff0c;数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O&#xff08;n&#xff09;。 ❖ 解法一&#xff1a;举例分析数组的规…

C#两大知名Redis客户端连接哨兵集群的姿势

前言前面《Docker-Compose搭建Redis高可用哨兵集群》&#xff0c;我的思路是将Redis、Sentinel、Redis Client App链接到同一个网桥网络&#xff0c;这个网桥内的Redis Client App就可以使用ContainerIP访问网桥内任意redis节点。同一网桥网络访问规避了Docker上发生的NAT&…

Docker之Dockerfile详解

使用Dockerfile创建镜像 Dockerfile是一个文本格式的配置文件&#xff0c;我们可以利用Dockerfile来快速的创建一个自定义的镜像。 基本结构 Dockerfile由一行命令语句组成&#xff0c;并且支持以#开头的注释一般包括四个部分&#xff1a;基础镜像信息&#xff0c;维护者信息…

[剑指offer]面试题34:丑数

面试题34&#xff1a;丑数 题目&#xff1a;我们把只包含因子2、3和5的数称作丑数&#xff08;Ugly Number&#xff09;。求按从小到大的顺序的第1500个丑数。例如6、8都是丑数&#xff0c;但14不是&#xff0c;因为它包含因子7。习惯上我们把1当做第一个丑数。 ❖ 逐个判断每…

创业的N种死法

点击蓝字关注&#xff0c;回复“职场进阶”获取职场进阶精品资料一份互联网的江湖一直流传着大佬们的创业传奇。马云上厕所几分钟敲定几千万美金融资。王石走投无路靠倒卖玉米赚到上百万从此逆袭。扎克伯格为了获得哈佛美女照片&#xff0c;开发一个小玩意从此改变了世界。传奇…

Docker容器实战思维

Docker成功的基础 Docker的实现用到的基础技术&#xff08;cgroups, namespace&#xff0c;分层文件系统&#xff09;在Docker之前已经存在很多年&#xff0c;并且 Linux Containers&#xff08;LXC&#xff09;也在很多企业的环境中得到了大量的应用实践&#xff0c;并得到明…

[剑指offer]面试题35:第一个只出现一次的字符

面试题35&#xff1a;第一个只出现一次的字符 题目&#xff1a;在字符串中找出第一个只出现一次的字符。如输入"abaccdeff"&#xff0c;则输出’b’。 代码如下: char FirstNotRepeatingChar(char *pString) {if (pString nullptr) return \0;const int tableSize…

dotNET Core 3.X 请求处理管道和中间件的理解

理解 dotNET Core 中的管道模型&#xff0c;对我们学习 dotNET Core 有很大的好处&#xff0c;能让我们知其然&#xff0c;也知其所以然&#xff0c;这样在使用第三方组件或者自己写一些扩展时&#xff0c;可以避免入坑&#xff0c;或者说避免同样的问题多次入坑。本文分为以下…

数据结构与算法--实现Singleton模式

题目&#xff1a;设计一个类&#xff0c;我们只生成该类的一个实例。 只生成一个实例的类就是实现Singleton&#xff08;单例&#xff09;模式的类型。本题其实主要考察我们设计模式&#xff0c;因为面试的时候先来一个简单的&#xff0c;并且喜欢面设计模式相关的题目&#x…

[剑指offer]面试题37:两个链表的第一个公共结点

面试题37&#xff1a;两个链表的第一个公共结点 题目&#xff1a;输入两个链表&#xff0c;找出它们的第一个公共结点。链表结点定义如下&#xff1a; struct ListNode {int val;ListNode *next;ListNode(int x) : val(x), next(NULL) {} };思路: 两个链表长度分别为L1C、L2C&…

了解.NET中的垃圾回收

原文来自互联网&#xff0c;由长沙DotNET技术社区编译。尽管这是一篇来自2009年的古老的文章&#xff0c;但或许能够对你理解GC产生一些作用。 了解.NET中的垃圾回收一旦了解了.NET的垃圾收集器是如何工作的&#xff0c;那么可能会触及.NET应用程序的一些更为神秘的问题时&…

数据结构与算法--数组:二维数组中查找

数组 数组最简单的是数据结构&#xff0c;占据一整块连续的内存并按照顺序存储数据&#xff0c;创建数组时候&#xff0c;我们需要首先指定数组的容量大小&#xff0c;然后根据大小分配内存。即使我们只在数组中存储一个元素&#xff0c;亚需要为所有数据预先分配内存&#xf…