Docker 基础 - 1

镜像

获取镜像

docker pull

查看镜像信息

docker images

docker inspect <images id> # 获取镜像的详细信息

搜寻镜像

docker search

删除镜像

docker rmi

当一个镜像拥有多个标签,docker rmi 只是删除该镜像指定的标签,并不影响镜像文件
当镜像只剩下一个标签时,再使用会彻底删除该镜像
先删除该镜像的所有容器,再删除镜像

创建镜像

2 种方法:

  • 基于已有镜像的容器创建
  • 基于 Dockerfile 创建(推荐)

基于已有镜像的容器创建

docker commit

-a: 作者信息
-m: 提交信息
-p 提交时暂停容器运行
-c changelist

存出和载入镜像

存出sudo docker save -o ubuntu_16.04.tar ubuntu:16.04

载入sudo docker load --input ubuntu_16.04.tar 或者 sudo docker load < ubuntu_16.04.tar

导入镜像,以及其相关的元数据信息(包括标签等)

容器

创建容器

使用交互式来运行容器:sudo docker run -it ubuntu:latest /bin/bash

docker run在后台执行的标准操作:

  1. 检查本地是否存在指定的镜像, 不存在就从公有仓库下载
  2. 利用镜像创建启动一个容器
  3. 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
  4. 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去。
  5. 从地址池配置一个 IP 地址给容器
  6. 执行用户指定的应用程序
  7. 执行完毕后容器被终止

守护态运行

sudo docker run -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"

通过docker logs命令获取容器的输出信息:sudo docker -tf logs 2855b4d76ccb

-t: 打印时间戳
-f: 刷新日志到最后
2855b4d76ccb: 容器id

终止容器

sudo docker stop 2855b4d76ccb

查看所有容器的信息:sudo docker ps -a

处于终止状态的容器,可以通过 docker start 命令来重新启动:sudo docker start 2855b4d76ccb

重启容器:sudo docker restart 2855b4d76ccb

进入容器

attach指令

sudo docker attach 2855b4d76ccb

当多个窗口同时 attach 到同一个容器时, 所有窗口会同步显示。当某个窗口因命令阻塞时,其他窗口也无法执行操作。

exec 命令

sudo docker exec -ti 2855b4d76ccb /bin/bash

删除容器

sudo docker rm 2855b4d76ccb

-f 强制删除运行中的容器
-l 删除容器链接,但保留容器
-v 删除容器挂载的数据卷

导入/导出容器

导出

sudo docker export 2855b4d76ccb > test.tar

可以将这些文件传输到其他机器上, 在其他机器上通过导入命令实现容器迁移

导入

cat test.tar | sudo docker import - test/ubuntu:v1.0

docker load 导入镜像存储文件到本地的镜像库
docker import 导入一个容器快照到本地镜像库

区别:

容器快照文件将丢弃所有的历史记录和元数据信息(仅保存容器当时的快照状态),导入时可以重新指定标签等元数据信息。
镜像存储文件将保存完整记录, 体积也大。

仓库

Docker Hub

登录

docker login

搜索

docker search

docker tag

sudo docker tag ubuntu:14.04 10.0.2.2:5000/test

自动创建

步骤:

  1. 登录 Docker Hub, 连接 GitHub 到 Docker
  2. 在Docker Hub 中配置自动创建:http://hub.docker.com/add/automated-build/caseycui/
  3. 选取一个目标网站项目(需要含 Dockerfile)和分支
  4. 指定 Dockerfile 的位置,并提交创建
  5. 之后,可以在 Docker Hub 的“自动创建”页面中跟踪每次创建的状态。

创建和使用私有仓库

使用 registry 镜像创建私有仓库

sudo docker -d -p 5000:5000 -v /opt/docker/registry/:/tmp/registry registry

监听端口映射到 5000,docker 容器中的 /tmp/registry 被映射到本地的 /opt/docker/registry/ 上。

管理私有仓库镜像

  • 修改 tag 的 REGISTRYHOST sudo docker tag ubuntu:latest 172.17.0.1:5000/test
  • 使用 docker push 上传 sudo docker push 172.17.0.1:5000/test
  • 使用docker pull 下载 sudo docker pull 172.17.0.1:5000/test

数据管理

两种方式:

  • 数据卷(Data Volumes)
  • 数据卷容器(Data Volume Containers)

数据卷

特性:

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

类似 Linux 的 mount 操作

挂载一个主机目录作为数据卷

sudo docker run -v /src/webapp:/opt/webapp training/webapp python app.py

加载主机的/src/webapp 目录到容器的 /opt/webapp 目录.

主机目录必须是绝对路径

默认权限是读写(rw), 可以设置为只读(ro) /src/webapp:/opt/webapp:ro

数据卷容器

数据卷容器其实就是普通的容器, 专门用它提供数据卷供其他容器挂载使用.

  1. 创建一个数据卷容器: sudo docker run -it -v /dbdata --name dbdata ubuntu

  2. 在其他容器中使用 volumes-from 来挂载 dbdata 容器中的数据卷.

    
    
    sudo docker run -it --volumes-from dbdata --name db1 ubuntu
    
    
    sudo docker run -it --volumes-from dbdata --name db2 ubuntu
    
    
    

    3个容器任何一方在该目录写入, 其他容器都可以看到。
    如果删除了容器, 数据卷并不会自动删除. 如果要删除数据卷, 必须在删除最后一个挂载着它的容器时显式使用 docker rm -v 命令来指定同时删除关联的容器

利用数据卷容器迁移数据

备份

sudo docker run --volumes-from dbdata -v $(pwd):/backup --name worker ubuntu tar cvf /backup/backup.tar /dbdata

恢复

sudo docker run -v /dbdata --name dbdata2 ubuntu /bin/bash
sudo docker run --volumes-from dbdata2 -v $(pwd):/backup busybox tar xvf /backup/backup.tar

网络基础配置

端口映射实现访问容器

sudo docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py

-P: 映射到随机端口

查看端口映射配置

sudo docker port loving_montalcini

容器互联实现容器间通信

容器的连接(linking)系统, 它会在源和接收容器之间创建一个隧道, 接收容器可以看到源容器指定的信息.

连接系统依据容器的名称来执行.

在执行 docker run 的时候如果添加 --rm 标记, 则容器在终止后会立即删除. --rm-d 无法同时使用.

容器互联

sudo docker run -d --name db training/postgres  # 创建一个新的数据库容器
sudo docker run -d -P --name web --link db:db training/webapp python app.py  # --link name:alias alias是连接的别名

Docker通过2种方式为容器公开连接信息:

  • 环境变量
  • 更新 /etc/hosts 文件

使用 env 命令查看web容器的环境变量:

$ docker exec web env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=62b19d3b5add
DB_PORT=tcp://172.17.0.2:5432
DB_PORT_5432_TCP=tcp://172.17.0.2:5432
DB_PORT_5432_TCP_ADDR=172.17.0.2
DB_PORT_5432_TCP_PORT=5432
DB_PORT_5432_TCP_PROTO=tcp
DB_NAME=/web/db
DB_ENV_PG_VERSION=9.3
HOME=/root

/etc/hosts 文件:

$ docker exec web cat /etc/hosts

127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

172.17.0.2      db 4288c4f9ad47
 
172.17.0.3      62b19d3b5add  # 本容器

也可以通过 ping 来测试:

$ docker exec web ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.083 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.054 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.054 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.053 ms
64 bytes from 172.17.0.2: icmp_seq=5 ttl=64 time=0.055 ms
64 bytes from 172.17.0.2: icmp_seq=6 ttl=64 time=0.057 ms

使用 Dockerfile 创建镜像

基本结构

  • 基础镜像信息
  • 维护者信息
  • 镜像操作指令
  • 容器启动时执行指令

指令

FROM

第一条指令必须为 FROM 指令

MAINTAINER(已弃用)

制定维护者信息. 以后可以用 LABEL maintainer="CaseyCui cuikaidong@foxmail.com"

RUN

两种格式:

  • RUN <command> bash格式, 命令在bash中运行, 默认在Linux是 /bin/sh -c 在windows上是 cmd /S /C
  • RUN ["executable", "param1", "param2"] (用 docker exec 执行)

每条RUN指令将在当前镜像基础上执行指定命令, 并提交为新的镜像.

最佳实践:

apt-get安装:

RUN apt-get update && apt-get install -y --no-install-recommends \
    aufs-tools \
    automake \
    build-essential \
    curl \
    dpkg-sig \
    libcap-dev \
    libsqlite3-dev \
    mercurial \
    reprepro \
    ruby1.9.1 \
    ruby1.9.1-dev \
    s3cmd=1.1.* \
&& rm -rf /var/lib/apt/lists/*

apt-get update && apt-get install 合用

apt-get install -y --no-install-recommends 不安装其他推荐的包, -no-install-suggests 也可以加上

ruby1.9.1 s3cmd=1.1.* 安装指定版本的包

rm -rf /var/lib/apt/lists/* 删除软件包残留

## a few minor docker-specific tweaks
## see http://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap
RUN set -xe \
    \
## http://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L40-L48
    && echo '#!/bin/sh' > /usr/sbin/policy-rc.d \
    && echo 'exit 101' >> /usr/sbin/policy-rc.d \
    && chmod +x /usr/sbin/policy-rc.d \
    \
## http://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L54-L56
    && dpkg-divert --local --rename --add /sbin/initctl \
    && cp -a /usr/sbin/policy-rc.d /sbin/initctl \
    && sed -i 's/^exit.*/exit 0/' /sbin/initctl \
    \
## http://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L71-L78
    && echo 'force-unsafe-io' > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup \
    \ 
## http://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L85-L105
    && echo 'DPkg::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' > /etc/apt/apt.conf.d/docker-clean \
    && echo 'APT::Update::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' >> /etc/apt/apt.conf.d/docker-clean \
    && echo 'Dir::Cache::pkgcache ""; Dir::Cache::srcpkgcache "";' >> /etc/apt/apt.conf.d/docker-clean \
    \
## http://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L109-L115
    && echo 'Acquire::Languages "none";' > /etc/apt/apt.conf.d/docker-no-languages \
    \ 
## http://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L118-L130
    && echo 'Acquire::GzipIndexes "true"; Acquire::CompressionTypes::Order:: "gz";' > /etc/apt/apt.conf.d/docker-gzip-indexes \
    \ 
## http://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L134-L151
    && echo 'Apt::AutoRemove::SuggestsImportant "false";' > /etc/apt/apt.conf.d/docker-autoremove-suggests

set -xe 调试模式, 返回非 0 (即不成功) 就退出

CMD

支持三种格式:

  • CMD ["executable","param1","param2"] 使用 docker exec 执行, 推荐方式
  • CMD ["param1","param2"] 作为 ENTRYPOINT 的默认参数
  • CMD command param1 param2 bash

指定启动容器时执行的命令, 每个 Dockerfile 只能有一条 CMD 命令.

EXPOSE

EXPOSE 80 8443

暴露的端口号, 供互联系统使用. 在启动时可以通过 -P-p 来指定映射

ENV

ENV PG_MAJOR 9.3
ENV PG_VERSION 9.3.4
RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && …
ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH

ADD

推荐只在 src 为 tar 文件时(会自动解压)使用. 其他时候使用 COPY. 不推荐使用 URL 的方式.

COPY

COPY <src> <dest> 当使用本例目录为 src 时, 推荐使用 COPY

ENTRYPOINT

两种格式:

  • ENTRYPOINT ["executable", "param1", "param2"] exec 格式
  • ENTRYPOINT command param1 param2 bash 格式

VOLUME

创建一个可以从本地主机或其他容器挂载的挂载点, 一般用来存放数据库和需要保持的数据等.

USER

指定运行容器时的用户名或 UID, 后续的 RUN 也会使用指定用户.

当服务不需要管理员权限时, 可以通过该命令指定运行用户.

要临时获取管理员权限推荐使用 gosu , 不推荐sudo

WORKDIR

为后续的 RUN CMD ENTRYPOINT 指令配置工作目录.

ONBUILD

ONBUILD [Dockerilfe的指令]

配置当所创建的镜像作为其他新创建镜像的基础镜像时, 所执行的操作指令.

使用 ONBUILD 指令的镜像, 推荐在 tag 中注明, 如 ruby:1.9-onbuild

创建镜像

docker build [选项] 路径

实现:

  1. 读取指定路径下(包括子目录)的 Dockerfile
  2. 将该路径下所有内容发送给 Docker 服务端
  3. 由服务端来创建镜像

一般建议放置 Dockerfile 的目录为空目录

可以通过 .dockerignore 文件来让 Docker 忽略路径下的目录和文件.

## comment
*/temp*
*/*/temp*
temp?

指令示例: sudo docker build -t build_repo/first_image /tmp/docker_builder/

三人行, 必有我师; 知识共享, 天下为公. 本文由东风微鸣技术博客 EWhisper.cn 编写.

本文转载于网络 如有侵权请联系删除

相关文章

  • 二、首页影院/我的 栏制作《仿淘票票系统前后端完全制作(除支付外)》

    页面效果,影院内容: 我的页分为登录、注册、我的,如果登录了那么就显示我的页面否则显示登录页。 登录页: 我的页:一、标题头部制作接着我们点击影院,发现当前页内容为空: 我们的影院页面跟首页内容类似,此时我们先复制首页的标题到影院页面: 删除右侧栏目的内容以及logo区域内容: 此时在右侧添加一个下拉菜单以及一个图标: 图标为search: 此时你还需要更改这些图标的属性内容,使其能够大小合适与当前页面。接着我们发现当前右边栏并不垂直居中,我们需要更改右侧栏的垂直对齐为居中: 这样的话,这个标题就做完了。二、内容区域制作接着制作内容区域,我们发现内容区域跟首页的内容类似,也是需要对应的内边距,此时只需要复制首页栏部分的内容行到当前页面之中即可: 此时是需要删除其他内容的,保留热映内容作为等下影院信息的内容部分。复制过去后,更改热映内容名称为影院地点: 接着添加一个图片,作为广告图,并且需要设置其宽度为100%,否则就按照原本的比例显示了: 其实这个影院信息还有个新人价的,之前截图没截全,此时页面应该如下: 我们可以从图中得知,当前影院信息内部分为左侧和右侧,左侧是影院

  • EL表达式的11个隐含对象

    是EL表达式中自己定义的,可以直接使用变量类型作用pagecontextpagecontextImpl他可以获取jsp中的九大内置对象pagescopemap他可以获取pagecontext域中的数据requestscopemap他可以获取request域中的数据sessionscopemap他可以获取session域中的数据applicationscopemap他可以获取application域中的数据parammap他可以获取请求参数的值paramvaluesmap他可以获取请求参数的值,获取多个值的时候使用、headermap他可以获取请求头的信息headervaluesmap他可以获取请求头的信息,可以获取多个值的情况cookiemap他可以获取当前请求的cookie信息initParammap他可以获取在web.xml中配置的上下文参数本文共166个字数,平均阅读时长≈1分钟

  • C语言递归求n的阶乘

    例30:C语言求n!,要求用递归实现。解题思路:本题和例29思想差不多,都是用递归来实现,读者可以回顾一下《C语言|递归求年龄》求阶乘函数:intfactorial(int number)//自定义阶乘函数  {   inttemp;//定义整型变量    if(number<0)//如果这个数小于0    {     printf("错误数据请,输入大于0的数!");//不符合条件,无法求    }   else if(number==0||number==1)//0或者1本身的阶乘是1    {     temp=1;   }   else   {     temp=factorial(number-1)*number;//否则求这个数与前一个数相乘的结果    }    return temp;//将temp返回到函数调用处  }复制源代码演示:#include<stdio.h>//头文件  int main()//主函数  {   int factorial(int number);//自定义阶乘函数声明    int number,tem

  • Angular Component 开发时属性和运行时属性的对照

    看个具体的例子:@Component({ selector:'cx-carousel', template:` <ng-container*ngFor="letitem$ofitems"> <ng-container *ngTemplateOutlet="template;context:{item:item$|async}" ></ng-container> </ng-container> `, }) classMockCarouselComponent{ @Input()title:string; @Input()template:TemplateRef<any>; @Input()items:any[]; }复制图中蓝色高亮的items和template属性需要消费端传入:下图是在另一个ComponentUI里消费MockCarouselComponent:中括号里的items,title和template就是MockCarouselComponent使用@In

  • 一图了解,网络7层协议之间的关系

    今天是周四(2020-06-04),分享一句谚语“读书有三到,心到口到眼到”。分享给大家的是「网络服务模块」-网络7层协议。本来这篇文章已经发过了,结果因为群主自己的失误,导致标题图错误,忘记切换。群主星座:“处女座”,不删除,看着都难受。因此大家也可以再次回忆回忆。欢迎热爱IT编程的各位精英,欢迎进入wechat技术群(底部有二维码),已经有2000+的朋友在不同技术群,一起交流成长。 花几分钟时间看看网络七层协议,浏览浏览,一定对你有用!!!1先来一波图,说明全文。2应用层与其它计算机进行通讯的一个应用,它是对应应用程序的通信服务的。例如,一个没有通信功能的字处理程序就不能执行通信的代码,从事字处理工作的程序员也不关心OSI的第7层。但是,如果添加了一个传输文件的选项,那么字处理器的程序就需要实现OSI的第7层。表示层这一层的主要功能是定义数据格式及加密。例如,FTP允许你选择以二进制或ASCII格式传输。如果选择二进制,那么发送方和接收方不改变文件的内容。如果选择ASCII格式,发送方将把文本从发送方的字符集转换成标准的ASCII后发送数据。在接收方将标准的ASCII转换成接收方

  • 监控软件的灰与黑:为了偷看手机我们付出了什么?

    套用茨威格在《砍头皇后》的一句名言开篇:她那时候还太年轻,不知道所有命运赠送的礼物,早已在暗中标好了价格。对于那些深受间谍软件危害的人们来说,可以换一个说法:他们那时候还太年轻,不知道自己的手机系统里,早已被人暗中装上了监控。这里要谈及的间谍软件,主要是针对手机等移动端设备进行隐私信息的监控和收集的应用。对于很多人来说,间谍软件的话题可能比较陌生,但却非常敏感。陌生在于我们确实很少见识到这种事情;敏感在于这个问题其实与我们息息相关。因为问题的根源来自于一个普遍的生活问题——你有没有想过偷看孩子或伴侣的手机?或者,你的手机有没有被别人看过?现在手机已经成为人们最主要的隐私之地。与其偷偷摸摸地打开别人手机看一下他的聊天记录,远不如安装一个悄无声息就可以获知一切信息的间谍软件更具诱惑力。使用这类间谍软件的也有两种场景:第一类最为典型,就是家长为了监控孩子上网行为而安装的监控。因为涉及监护权与未成年人隐私保护的复杂关系上,这一类产业处于比较敏感的灰色地带。而再一类是成年人之间在不知情的情况下的监控行为,比如伴侣、同事之间,更别说商业竞争关系之间的秘密监控,则明显属于存在违法行为的黑色产业。因此

  • JMS的常用方法

    importjavax.jms.Connection; importjavax.jms.ConnectionFactory; importjavax.jms.Destination; importjavax.jms.Message; importjavax.jms.MessageConsumer; importjavax.jms.MessageListener; importjavax.jms.Session; importjavax.jms.TextMessage; importorg.apache.activemq.ActiveMQConnection; importorg.apache.activemq.ActiveMQConnectionFactory; importcom.ailk.biapp.ci.localization.cntv.service.IUserSynchronizationService; importcom.asiainfo.biframe.utils.config.Configure; importcom.asiainfo.biframe.utils.

  • 微服务的故障处理

    当微服务发生故障后怎么办?最近线上发生一起故障,一个接口的慢查询拖垮了整个应用,导致整个应用变得不可用。如果正好赶上流量高峰,应用重启都变得很困难,除非把入口整个关闭,再重启应用等待应用的恢复。 在复盘时,结论是增加上线审核流程和控制来试图阻止故障的再次发生,很少花费心思想想如何更加容易地在第一时间从故障中恢复过来。 在这次故障中我也做了一些思考,如果当时是我处理这起故障,我能做什么?本文因此而起,一部分来自于之前公司所做的稳定性建设方面的经验,一部分来源于《微服务设计》中所写的经验。分成技术实现前的思考和技术方面可以做的事情。 一技术实现前的思考 思考一、假定故障会发生,如何去优雅地处理它。 假设一切都会失败,会让你从不同的角度去思考如何解决问题。我们可以在试图阻止不可避免的故障上少花一点时间,而花更多时间去优雅地处理它。假定故障会发生,如果以这种想法来处理你做的每一件事情,为其故障做好准备,那么就会做出不同的权衡。 了解你可以容忍多少故障,或者系统需要多快,了解系统的用户的负载能力。 思考二、系统的强弱依赖梳理 梳理系统下游接口强弱程度,哪些接口是强依赖,哪一些是弱依赖。强依赖一般

  • 设计模式/原则篇- Unit of Work

    概念  UnitofWork即工作单元。用来维护一组受业务影响的对象列表,将多个操作放在一个单元中,把操作原子化,通过事务统一完成一次提交,如果某个过程出现异常,就将所有修改进行回滚,保证数据的有效状态。同时减少了应用程序与数据库通信,有利于提升系统的性能。   具体使用(银行领域的转账建模) 整体项目结构预览 构建UnitOfWork.Infrastructure 1、新建Domain文件夹,添加IAggregateRoot接口 IAggregateRoot接口属于聚合根,所有业务对象(Entity)都需要实现聚合根。外部对象需要访问聚合内的实体时,只能通过聚合根进行访问,而不能直接访问。领域模型需要根据领域概念分成多个聚合,每个聚合都有一个实体作为聚合根,通俗的说,领域对象从无到有的创建,以及CRUD的操作都应该作用于聚合根上,而不是单独的某个实体。 2、新建UnitofWork文件夹,添加IUnitofWorkRepository接口 voidPersistCreationOf(IAggregateRootentity); voidPersistUp

  • Codeforces Round #724 (Div. 2)C. Diluc and Kaeya(思维)

    题目大意:一个D、K组成的字符串。求其每个前缀最多能分割成几个子串,使被分割的每个串的sumD:sumK相等。 题解:每个前缀被分割子串的sumD:sumK的值,就是整个前缀sumD:sumK的值,从左到右扫,累计答案。 #include<iostream> #include<cstdio> #include<map> #include<cstring> #include<algorithm> usingnamespacestd; #defineN500001 intt; chars[N]; intsumd[N],sumk[N]; typedefpair<int,int>PII; intgcd(intx,inty) { returny==0?x:gcd(y,x%y); } intmain() { scanf("%d",&t); while(t--) { intn; scanf("%d",&n); scanf("%s",s+1); map<PII,int>a; for(int

  • T3 网格游走

    本质上是一道trajan构图+floodfill+期望的壳子 对于高度来说,我们自然需要重新建图:-》知识点:二维变成一维的图 return(x-1)*m+y复制 那么新图就建出来了:同时我们可以考虑(现在这个图是DAG吗?显然不是,那么我们往往特殊走:如果一块之间是DAG我们会怎么处理) 如果是DAG的话,我们显然可以从多个入度为0(对于DAG一定要关注入度或者出度为0的点)进入队列,然后用floodfill的思想从多个角度top序更新 那么:怎么样才能够锁点?: trajan缩完点之后,我们要关注的是缩完点之后的点的性质:以本题为例,缩完之后的点贡献期望是多少 这时候需要根据期望的递推式进行记忆化搜搜:    最后一定要关注一个东西:用暴力求解得出来的答案可以尝试打表一下观察他们的特殊性:本题fi=2i 代码: #include<iostream> #include<cstdio> #include<cstring> #include<queue> #definelllonglong usin

  • 智能语音唤醒词,自学习意义与步骤

    语音自学习的意义 为了提高唤醒词的识别准确率,让移动终端更准确地认出主人的唤醒, 需要训练并让移动终端通过自我学习,记忆保存主人的唤醒声音。 唤醒词语音自学习的步骤 以荣耀v20为例,其唤醒词是“你好yoyo”, 通过录音机App录制一个“你好yoyo”的文件,命名为:wakeup.mp3 进入设置,智慧助手,智慧语音,语音唤醒,唤醒词,进入自学习界面 连续3次播放这个“你好yoyo”的wakeup.mp3文件,让手机记住主人的唤醒声音。 自学习成功! 后续只要播放wakeup.mp3这个文件,就可以快速唤醒手机的智能语音! 更多更好的原创文章,请访问官方网站:www.zipython.com 自拍教程(自动化测试Python教程,武散人编著) 原文链接:https://www.zipython.com/#/detail?id=e72446ad65f84d3482821d37e6d37820 也可关注“武散人”微信订阅号,随时接受文章推送。

  • 转 分页实现:Offset-Fetch

    作者:悦光阴 出处:http://www.cnblogs.com/ljhdo/ 本文版权归作者和博客园所有,欢迎转载,但未经作者同意,必须保留此段声明,且在文章页面醒目位置显示原文连接,否则保留追究法律责任的权利。   分页实现的方法又多了一种,在SQL Server2012版本中,TSQL在OrderBy子句中新增Offset-Fetch子句,用于从有序的结果集中,跳过一定数量的数据行,获取指定数量的数据行,从而达到数据行分页的目的。经过测试,从逻辑读取数量和响应的时间消耗来测评,使用Offset-Fetch实现的分页方式,比Row_Number()方式性能要高很多。 Offset-Fetch子句要求结果集是有序的,因此,只能用于orderby子句中,语法如下: ORDERBYorder_by_expression[ASC|DESC][,...n][<offset_fetch>] <offset_fetch>::= { OFFSET{integer_constant|offset_row_count_expression}ROWS [F

  • qt缩放参考

    #include"widget.h" #include<QApplication> #include<QObject> #include<QWidget> #include<QDesktopWidget> #include<QMessageBox> //#include<stdio.h> //#include<string> #include"windows.h" #pragmacomment(lib,"User32.lib") #pragmaexecution_character_set("utf-8") intmain(intargc,char*argv[]) { QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);//控制图片缩放质量 //QGuiApplication::setHighDpiScaleFa

  • SRS文档 用例建模

    SRS文档 用例建模

  • 深入学习Netty(1)——传统BIO编程

    前言   之前看过Dubbo源码,Nacos等源码都涉及到了Netty,虽然遇到的时候查查资料,后面自己也有私下学习Netty并实践,但始终没有形成良好的知识体系,Netty对想要在Java开发上不断深入是十分重要的。所以借此博客平台记录下自己的学习思考的过程,形成自己的知识体系,以后学习深入源码更加得心应手!   参考资料《NettyInAction》、《Netty权威指南》(有需要的小伙伴可以评论或者私信我)   博文中所有的代码都已上传到Github,欢迎Star、Fork     一、Linux中常见的I/O模型 1.5种I/O模型 根据UNIX网络编程对I/O模型的分类,UNIX提供了5种I/O模型 (1)阻塞I/O模型   如果还未获取数据报则一直等待,直到数据报准备好了再进行复制数据报等接下来的操作。 (2)非阻塞I/O模型   轮询检查是否有数据准备好的状态,如果数据准备好就进行接下来的操作 (3)I/O复用模型   Linux提供select/poll,进程通过将一个或多个fd传递给select或poll系统调用,这样select/poll可

  • 命令安装VS

       InstallingVisualStudio VisualStudio2015   OtherVersions VisualStudio2013 VisualStudio2010 VisualStudio2008 VisualStudio2005 VisualStudio.NET2003   ToinstallVisualStudio2015,youcanusetheinstallationmediafromaboxedproduct,oryoucandownloadtheinstallationfilesfromvisualstudio.com. ForinformationabouteacheditionofVisualStudio2015,includingsystemrequirements,seeCompareVisualStudioOfferings. Thisdocumentprovidesthefollowinginstallationinformation: Typicalvs.Cu

  • JSON工具类的构建(前端版本)

    前言 在前后端交互的选择上,之前一直采用的是模板引擎(因为我只负责后端)。 而这次的一个算是作业吧,前后端都是我,所以就研究了一下JSON交互在javaweb的应用(主要是前端)。 优缺点 因为我是先写后端版本的,所以优缺点部分请跳转至JSON工具类的构建(后端版本)查看。 对比 因为我对js也是几天速成系列,所以框架型的jq以及ajax也是处于概念上的理解以及皮毛型的应用。 我所认识的主流的前端处理的ajax,所以就选用了ajax进行发送/接收解析json的处理。 需求拆分 因为没有打算深入学习前端,所以对需求的划分以及功能实现只限于满足这次的作业。 而我定义的功能/需求主要有两个 外部函数只需进行传入接口url以及数据,接收并初步解析结果 必须能进行get/post请求的发送以及接收 只需要发送单实体数据 格式设计 因为是请求型报文,所以只需要形成普通的json格式 { "name":"name", "password":"password", "account":"account" } 复制 代码设计 因为我希望传入接口url以及数据既能完成数据的发送与接收,而个人觉得aja

  • E. Holes(分块)

    题目链接: E.Holes timelimitpertest 1second memorylimitpertest 64megabytes input standardinput output standardoutput LittlePetyalikestoplayalot.Mostofallhelikestoplayagame«Holes».Thisisagameforonepersonwithfollowingrules: Thereare N holeslocatedinasinglerowandnumberedfromlefttorightwithnumbersfrom1to N.Eachholehasit'sownpower(holenumber i hasthepower ai).Ifyouthrowaballintohole i itwillimmediatelyjumptohole i + ai,thenitwilljumpoutofitandsoon.Ifther

  • jQuery移动优先的炫酷环形菜单插件

    FerroMenu是一款炫酷的移动优先的jQuery环形气泡菜单特效插件。该环形气泡菜单插件可以让你很轻松的创建一个环形菜单,并且该菜单可以在屏幕上随意拖动到9个位置上(东、南、西、北、中方向和东南、西北、东北和西南方向)。该环形菜单的菜单项可以是锚链接、外部链接或javascript等等。该菜单展开的最终效果有点类似于超酷jQuery环形按钮菜单效果插件。FerroMenu环形气泡菜单的特点有: 可以将菜单拖动到屏幕的9个位置上:东、南、西、北、中方向和东南、西北、东北和西南方向。 可以通过拖动来移动菜单,当拖动结束时,环形菜单会自动移动到最接近的位置点上。 可以很轻松的通过CSS文件来定制环形菜单的样式。 能够通过设置来改变环形菜单的动画持续时间、easing效果、动画延时时间、旋转角度、打开关闭效果、菜单距离屏幕的margin、菜单项到主按钮的半径等属性。 环形菜单项会在菜单移动后根据可用空间重新排列。 可以设置使用或禁用拖动菜单选项。 滑动内容都被封装到一个容器中。 在线演示:http://www.htmleaf.com/Demo/201503031455.html 下

  • splay

    voidsplay(inti,inttar) { while(nd[i].fa!=tar){ intj=nd[i].fa; if(nd[j].fa!=tar&&who(i)==who(j)) rotate(j); rotate(i); } if(tar==-1)root=i; return; }复制 ViewCode 这个才是正确的写法!!! 这个才是正确的写法!!! 这个才是正确的写法!!! 之前的写法插入一条链然后依次删除就会出问题(多手动模拟几次)。 insert(0); insert(0); ...... insert(0); insert(1); remove(0); remove(0); ...... remove(0);

相关推荐

推荐阅读