mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-01-13 22:30:37 +08:00
Merge remote-tracking branch 'LCTT/master'
This commit is contained in:
commit
49704163fa
@ -0,0 +1,204 @@
|
||||
Python 的 ChatOps 库:Opsdroid 和 Errbot
|
||||
======
|
||||
|
||||
> 学习一下 Python 世界里最广泛使用的 ChatOps 库:每个都能做什么,如何使用。
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/idea_innovation_mobile_phone.png?itok=RqVtvxkd)
|
||||
|
||||
ChatOps 是基于会话导向而进行的开发。其思路是你可以编写能够对聊天窗口中的某些输入进行回复的可执行代码。作为一个开发者,你能够用 ChatOps 从 Slack 合并拉取请求,自动从收到的 Facebook 消息中给某人分配支持工单,或者通过 IRC 检查开发状态。
|
||||
|
||||
在 Python 世界,最为广泛使用的 ChatOps 库是 Opsdroid 和 Errbot。在这个月的 Python 专栏,让我们一起聊聊使用它们是怎样的体验,它们各自适用于什么方面以及如何着手使用它们。
|
||||
|
||||
### Opsdroid
|
||||
|
||||
[Opsdroid][2] 是一个相对年轻的(始于 2016)Python 开源聊天机器人库。它有着良好的开发文档,不错的教程,并且包含能够帮助你对接流行的聊天服务的插件。
|
||||
|
||||
#### 它内置了什么
|
||||
|
||||
库本身并没有自带所有你需要上手的东西,但这是故意的。轻量级的框架鼓励你去运用它现有的连接器(Opsdroid 所谓的帮你接入聊天服务的插件)或者去编写你自己的,但是它并不会因自带你所不需要的连接器而自贬身价。你可以轻松使用现有的 Opsdroid 连接器来接入:
|
||||
|
||||
+ 命令行
|
||||
+ Cisco Spark
|
||||
+ Facebook
|
||||
+ GitHub
|
||||
+ Matrix
|
||||
+ Slack
|
||||
+ Telegram
|
||||
+ Twitter
|
||||
+ Websocket
|
||||
|
||||
Opsdroid 会调用使聊天机器人能够展现它们的“技能”的函数。这些技能其实是异步 Python 函数,并使用 Opsdroid 叫做“匹配器”的匹配装饰器。你可以设置你的 Opsdroid 项目,来使用同样从你设置文件所在的代码中的“技能”。你也可以从外面的公共或私人仓库调用这些“技能”。
|
||||
|
||||
你同样可以启用一些现存的 Opsdroid “技能”,包括 [seen][3] —— 它会告诉你聊天机器人上次是什么时候看到某个用户的,以及 [weather][4] —— 会将天气报告给用户。
|
||||
|
||||
最后,Opdroid 允许你使用现存的数据库模块设置数据库。现在 Opdroid 支持的数据库包括:
|
||||
|
||||
+ Mongo
|
||||
+ Redis
|
||||
+ SQLite
|
||||
|
||||
你可以在你的 Opdroid 项目中的 `configuration.yaml` 文件设置数据库、技能和连接器。
|
||||
|
||||
#### Opsdroid 的优势
|
||||
|
||||
**Docker 支持:**从一开始 Opsdroid 就打算在 Docker 中良好运行。在 Docker 中的指导是它 [安装文档][5] 中的一部分。使用 Opsdroid 和 Docker Compose 也很简单:将 Opsdroid 设置成一种服务,当你运行 `docker-compose up` 时,你的 Opsdroid 服务将会开启你的聊天机器人也将就绪。
|
||||
|
||||
```
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
opsdroid:
|
||||
container_name: opsdroid
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
```
|
||||
|
||||
**丰富的连接器:** Opsdroid 支持九种像 Slack 和 Github 等从外部接入的服务连接器。你所要做的一切就是在你的设置文件中启用那些连接器,然后把必须的口令或者 API 密匙传过去。比如为了启用 Opsdroid 以在一个叫做 `#updates` 的 Slack 频道发帖,你需要将以下代码加入你设置文件的 `connectors` 部分:
|
||||
|
||||
```
|
||||
- name: slack
|
||||
api-token: "this-is-my-token"
|
||||
default-room: "#updates"
|
||||
```
|
||||
|
||||
在设置 Opsdroid 以接入 Slack 之前你需要[添加一个机器人用户][6]。
|
||||
|
||||
如果你需要接入一个 Opsdroid 不支持的服务,在[文档][7]里有有添加你自己的连接器的教程。
|
||||
|
||||
**相当不错的文档:** 特别是对于一个在积极开发中的新兴库来说,Opsdroid 的文档十分有帮助。这些文档包括一篇带你创建几个不同的基本技能的[教程][8]。Opsdroid 在[技能][9]、[连接器][7]、[数据库][10],以及[匹配器][11]方面的文档也十分清晰。
|
||||
|
||||
它所支持的技能和连接器的仓库为它的技能提供了富有帮助的示范代码。
|
||||
|
||||
**自然语言处理:** Opsdroid 的技能里面能使用正则表达式,但也同样提供了几个包括 [Dialogflow][12],[luis.ai][13],[Recast.AI][14] 以及 [wit.ai][15] 的 NLP API。
|
||||
|
||||
#### Opsdroid 可能的不足
|
||||
|
||||
Opsdroid 对它的一部分连接器还没有启用全部的特性。比如说,Slack API 允许你向你的消息添加颜色柱、图片以及其他的“附件”。Opsdroid Slack 连接器并没有启用“附件”特性,所以如果那些特性对你来说很重要的话,你需要编写一个自定义的 Slack 连接器。如果连接器缺少一个你需要的特性,Opsdroid 将欢迎你的[贡献][16]。文档中可以使用更多的例子,特别是对于预料到的使用场景。
|
||||
|
||||
#### 示例用法
|
||||
|
||||
```
|
||||
from opsdroid.matchers import match_regex
|
||||
import random
|
||||
|
||||
|
||||
@match_regex(r'hi|hello|hey|hallo')
|
||||
async def hello(opsdroid, config, message):
|
||||
text = random.choice(["Hi {}", "Hello {}", "Hey {}"]).format(message.user)
|
||||
await message.respond(text)
|
||||
```
|
||||
|
||||
*hello/\_\_init\_\_.py*
|
||||
|
||||
|
||||
```
|
||||
connectors:
|
||||
- name: websocket
|
||||
|
||||
skills:
|
||||
- name: hello
|
||||
repo: "https://github.com/<user_id>/hello-skill"
|
||||
|
||||
```
|
||||
|
||||
*configuration.yaml*
|
||||
|
||||
|
||||
### Errbot
|
||||
|
||||
[Errbot][17] 是一个功能齐全的开源聊天机器人。Errbot 发行于 2012 年,并且拥有人们从一个成熟的项目能期待的一切,包括良好的文档、优秀的教程以及许多帮你连入现有的流行聊天服务的插件。
|
||||
|
||||
#### 它内置了什么
|
||||
|
||||
不像采用了较轻量级方式的 Opsdroid,Errbot 自带了你需要可靠地创建一个自定义机器人的一切东西。
|
||||
|
||||
Errbot 包括了对于本地 XMPP、IRC、Slack、Hipchat 以及 Telegram 服务的支持。它通过社区支持的后端列出了另外十种服务。
|
||||
|
||||
#### Errbot 的优势
|
||||
|
||||
**良好的文档:** Errbot 的文档成熟易读。
|
||||
|
||||
**动态插件架构:** Errbot 允许你通过和聊天机器人交谈安全地安装、卸载、更新、启用以及禁用插件。这使得开发和添加特性十分简便。感谢 Errbot 的颗粒性授权系统,出于安全意识这所有的一切都可以被锁闭。
|
||||
|
||||
当某个人输入 `!help`,Errbot 使用你的插件的文档字符串来为可获取的命令生成文档,这使得了解每行命令的作用更加简便。
|
||||
|
||||
**内置的管理和安全特性:** Errbot 允许你限制拥有管理员权限的用户列表,甚至细粒度访问控制。比如说你可以限制特定用户或聊天房间访问特定命令。
|
||||
|
||||
**额外的插件框架:** Errbot 支持钩子、回调、子命令、webhook、轮询以及其它[更多特性][18]。如果那些还不够,你甚至可以编写[动态插件][19]。当你需要基于在远程服务器上的可用命令来启用对应的聊天命令时,这个特性十分有用。
|
||||
|
||||
**自带测试框架:** Errbot 支持 [pytest][20],同时也自带一些能使你简便测试插件的有用功能。它的“[测试你的插件][21]”的文档出于深思熟虑,并提供了足够的资料让你上手。
|
||||
|
||||
#### Errbot 可能的不足
|
||||
|
||||
**以 “!” 开头:** 默认情况下,Errbot 命令发出时以一个惊叹号打头(`!help` 以及 `!hello`)。一些人可能会喜欢这样,但是另一些人可能认为这让人烦恼。谢天谢地,这很容易关掉。
|
||||
|
||||
**插件元数据** 首先,Errbot 的 [Hello World][22] 插件示例看上去易于使用。然而我无法加载我的插件,直到我进一步阅读了教程并发现我还需要一个 `.plug` 文档,这是一个 Errbot 用来加载插件的文档。这可能比较吹毛求疵了,但是在我深挖文档之前,这对我来说都不是显而易见的。
|
||||
|
||||
### 示例用法
|
||||
|
||||
|
||||
```
|
||||
import random
|
||||
from errbot import BotPlugin, botcmd
|
||||
|
||||
class Hello(BotPlugin):
|
||||
|
||||
@botcmd
|
||||
def hello(self, msg, args):
|
||||
text = random.choice(["Hi {}", "Hello {}", "Hey {}"]).format(message.user)
|
||||
return text
|
||||
```
|
||||
|
||||
*hello.py*
|
||||
|
||||
```
|
||||
[Core]
|
||||
Name = Hello
|
||||
Module = hello
|
||||
|
||||
[Python]
|
||||
Version = 2+
|
||||
|
||||
[Documentation]
|
||||
Description = Example "Hello" plugin
|
||||
```
|
||||
|
||||
*hello.plug*
|
||||
|
||||
|
||||
你用过 Errbot 或 Opsdroid 吗?如果用过请留下关于你对于这些工具印象的留言。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/3/python-chatops-libraries-opsdroid-and-errbot
|
||||
|
||||
作者:[Jeff Triplett][a], [Lacey Williams Henschel][1]
|
||||
译者:[tomjlw](https://github.com/tomjlw)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/laceynwilliams
|
||||
[1]:https://opensource.com/users/laceynwilliams
|
||||
[2]:https://opsdroid.github.io/
|
||||
[3]:https://github.com/opsdroid/skill-seen
|
||||
[4]:https://github.com/opsdroid/skill-weather
|
||||
[5]:https://opsdroid.readthedocs.io/en/stable/#docker
|
||||
[6]:https://api.slack.com/bot-users
|
||||
[7]:https://opsdroid.readthedocs.io/en/stable/extending/connectors/
|
||||
[8]:https://opsdroid.readthedocs.io/en/stable/tutorials/introduction/
|
||||
[9]:https://opsdroid.readthedocs.io/en/stable/extending/skills/
|
||||
[10]:https://opsdroid.readthedocs.io/en/stable/extending/databases/
|
||||
[11]:https://opsdroid.readthedocs.io/en/stable/matchers/overview/
|
||||
[12]:https://opsdroid.readthedocs.io/en/stable/matchers/dialogflow/
|
||||
[13]:https://opsdroid.readthedocs.io/en/stable/matchers/luis.ai/
|
||||
[14]:https://opsdroid.readthedocs.io/en/stable/matchers/recast.ai/
|
||||
[15]:https://opsdroid.readthedocs.io/en/stable/matchers/wit.ai/
|
||||
[16]:https://opsdroid.readthedocs.io/en/stable/contributing/
|
||||
[17]:http://errbot.io/en/latest/
|
||||
[18]:http://errbot.io/en/latest/features.html#extensive-plugin-framework
|
||||
[19]:http://errbot.io/en/latest/user_guide/plugin_development/dynaplugs.html
|
||||
[20]:http://pytest.org/
|
||||
[21]:http://errbot.io/en/latest/user_guide/plugin_development/testing.html
|
||||
[22]:http://errbot.io/en/latest/index.html#simple-to-build-upon
|
@ -1,364 +0,0 @@
|
||||
hankchow translating
|
||||
|
||||
Building tiny container images
|
||||
======
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/containers_scale_performance.jpg?itok=R7jyMeQf)
|
||||
|
||||
When [Docker][1] exploded onto the scene a few years ago, it brought containers and container images to the masses. Although Linux containers existed before then, Docker made it easy to get started with a user-friendly command-line interface and an easy-to-understand way to build images using the Dockerfile format. But while it may be easy to jump in, there are still some nuances and tricks to building container images that are usable, even powerful, but still small in size.
|
||||
|
||||
### First pass: Clean up after yourself
|
||||
|
||||
Some of these examples involve the same kind of cleanup you would use with a traditional server, but more rigorously followed. Smaller image sizes are critical for quickly moving images around, and storing multiple copies of unnecessary data on disk is a waste of resources. Consequently, these techniques should be used more regularly than on a server with lots of dedicated storage.
|
||||
|
||||
An example of this kind of cleanup is removing cached files from an image to recover space. Consider the difference in size between a base image with [Nginx][2] installed by `dnf` with and without the metadata and yum cache cleaned up:
|
||||
```
|
||||
# Dockerfile with cache
|
||||
|
||||
FROM fedora:28
|
||||
|
||||
LABEL maintainer Chris Collins <collins.christopher@gmail.com>
|
||||
|
||||
|
||||
|
||||
RUN dnf install -y nginx
|
||||
|
||||
|
||||
|
||||
-----
|
||||
|
||||
|
||||
|
||||
# Dockerfile w/o cache
|
||||
|
||||
FROM fedora:28
|
||||
|
||||
LABEL maintainer Chris Collins <collins.christopher@gmail.com>
|
||||
|
||||
|
||||
|
||||
RUN dnf install -y nginx \
|
||||
|
||||
&& dnf clean all \
|
||||
|
||||
&& rm -rf /var/cache/yum
|
||||
|
||||
|
||||
|
||||
-----
|
||||
|
||||
|
||||
|
||||
[chris@krang] $ docker build -t cache -f Dockerfile .
|
||||
|
||||
[chris@krang] $ docker images --format "{{.Repository}}: {{.Size}}"
|
||||
|
||||
| head -n 1
|
||||
|
||||
cache: 464 MB
|
||||
|
||||
|
||||
|
||||
[chris@krang] $ docker build -t no-cache -f Dockerfile-wo-cache .
|
||||
|
||||
[chris@krang] $ docker images --format "{{.Repository}}: {{.Size}}" | head -n 1
|
||||
|
||||
no-cache: 271 MB
|
||||
|
||||
```
|
||||
|
||||
That is a significant difference in size. The version with the `dnf` cache is almost twice the size of the image without the metadata and cache. Package manager cache, Ruby gem temp files, `nodejs` cache, even downloaded source tarballs are all perfect candidates for cleaning up.
|
||||
|
||||
### Layers—a potential gotcha
|
||||
|
||||
Unfortunately (or fortunately, as you’ll see later), based on the way layers work with containers, you cannot simply add a `RUN rm -rf /var/cache/yum` line to your Dockerfile and call it a day. Each instruction of a Dockerfile is stored in a layer, with changes between layers applied on top. So even if you were to do this:
|
||||
```
|
||||
RUN dnf install -y nginx
|
||||
|
||||
RUN dnf clean all
|
||||
|
||||
RUN rm -rf /var/cache/yum
|
||||
|
||||
```
|
||||
|
||||
...you’d still end up with three layers, one of which contains all the cache, and two intermediate layers that "remove" the cache from the image. But the cache is actually still there, just as when you mount a filesystem over the top of another one, the files are there—you just can’t see or access them.
|
||||
|
||||
You’ll notice that the example in the previous section chains the cache cleanup in the same Dockerfile instruction where the cache is generated:
|
||||
```
|
||||
RUN dnf install -y nginx \
|
||||
|
||||
&& dnf clean all \
|
||||
|
||||
&& rm -rf /var/cache/yum
|
||||
|
||||
```
|
||||
|
||||
This is a single instruction and ends up being a single layer within the image. You’ll lose a bit of the Docker (*ahem*) cache this way, making a rebuild of the image slightly longer, but the cached data will not end up in your final image. As a nice compromise, just chaining related commands (e.g., `yum install` and `yum clean all`, or downloading, extracting and removing a source tarball, etc.) can save a lot on your final image size while still allowing you to take advantage of the Docker cache for quicker development.
|
||||
|
||||
This layer "gotcha" is more subtle than it first appears, though. Because the image layers document the _changes_ to each layer, one upon another, it’s not just the existence of files that add up, but any change to the file. For example, _even changing the mode_ of the file creates a copy of that file in the new layer.
|
||||
|
||||
For example, the output of `docker images` below shows information about two images. The first, `layer_test_1`, was created by adding a single 1GB file to a base CentOS image. The second image, `layer_test_2`, was created `FROM layer_test_1` and did nothing but change the mode of the 1GB file with `chmod u+x`.
|
||||
```
|
||||
layer_test_2 latest e11b5e58e2fc 7 seconds ago 2.35 GB
|
||||
|
||||
layer_test_1 latest 6eca792a4ebe 2 minutes ago 1.27 GB
|
||||
|
||||
```
|
||||
|
||||
As you can see, the new image is more than 1GB larger than the first. Despite the fact that `layer_test_1` is only the first two layers of `layer_test_2`, there’s still an extra 1GB file floating around hidden inside the second image. This is true anytime you remove, move, or change any file during the image build process.
|
||||
|
||||
### Purpose-built images vs. flexible images
|
||||
|
||||
An anecdote: As my office heavily invested in [Ruby on Rails][3] applications, we began to embrace the use of containers. One of the first things we did was to create an official Ruby base image for all of our teams to use. For simplicity’s sake (and suffering under “this is the way we did it on our servers”), we used [rbenv][4] to install the latest four versions of Ruby into the image, allowing our developers to migrate all of their applications into containers using a single image. This resulted in a very large but flexible (we thought) image that covered all the bases of the various teams we were working with.
|
||||
|
||||
This turned out to be wasted work. The effort required to maintain separate, slightly modified versions of a particular image was easy to automate, and selecting a specific image with a specific version actually helped to identify applications approaching end-of-life before a breaking change was introduced, wreaking havoc downstream. It also wasted resources: When we started to split out the different versions of Ruby, we ended up with multiple images that shared a single base and took up very little extra space if they coexisted on a server, but were considerably smaller to ship around than a giant image with multiple versions installed.
|
||||
|
||||
That is not to say building flexible images is not helpful, but in this case, creating purpose-build images from a common base ended up saving both storage space and maintenance time, and each team could modify their setup however they needed while maintaining the benefit of the common base image.
|
||||
|
||||
### Start without the cruft: Add what you need to a blank image
|
||||
|
||||
As friendly and easy-to-use as the _Dockerfile_ is, there are tools available that offer the flexibility to create very small Docker-compatible container images without the cruft of a full operating system—even those as small as the standard Docker base images.
|
||||
|
||||
[I’ve written about Buildah before][5], and I’ll mention it again because it is flexible enough to create an image from scratch using tools from your host to install packaged software and manipulate the image. Those tools then never need to be included in the image itself.
|
||||
|
||||
Buildah replaces the `docker build` command. With it, you can mount the filesystem of your container image to your host machine and interact with it using tools from the host.
|
||||
|
||||
Let’s try Buildah with the Nginx example from above (ignoring caches for now):
|
||||
```
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -o errexit
|
||||
|
||||
|
||||
|
||||
# Create a container
|
||||
|
||||
container=$(buildah from scratch)
|
||||
|
||||
|
||||
|
||||
# Mount the container filesystem
|
||||
|
||||
mountpoint=$(buildah mount $container)
|
||||
|
||||
|
||||
|
||||
# Install a basic filesystem and minimal set of packages, and nginx
|
||||
|
||||
dnf install --installroot $mountpoint --releasever 28 glibc-minimal-langpack nginx --setopt install_weak_deps=false -y
|
||||
|
||||
|
||||
|
||||
# Save the container to an image
|
||||
|
||||
buildah commit --format docker $container nginx
|
||||
|
||||
|
||||
|
||||
# Cleanup
|
||||
|
||||
buildah unmount $container
|
||||
|
||||
|
||||
|
||||
# Push the image to the Docker daemon’s storage
|
||||
|
||||
buildah push nginx:latest docker-daemon:nginx:latest
|
||||
|
||||
```
|
||||
|
||||
You’ll notice we’re no longer using a Dockerfile to build the image, but a simple Bash script, and we’re building it from a scratch (or blank) image. The Bash script mounts the container’s root filesystem to a mount point on the host, and then uses the hosts’ command to install the packages. This way the package manager doesn’t even have to exist inside the container.
|
||||
|
||||
Without extra cruft—all the extra stuff in the base image, like `dnf`, for example—the image weighs in at only 304 MB, more than 100 MB smaller than the Nginx image built with a Dockerfile above.
|
||||
```
|
||||
[chris@krang] $ docker images |grep nginx
|
||||
|
||||
docker.io/nginx buildah 2505d3597457 4 minutes ago 304 MB
|
||||
|
||||
```
|
||||
|
||||
_Note: The image name has`docker.io` appended to it due to the way the image is pushed into the Docker daemon’s namespace, but it is still the image built locally with the build script above._
|
||||
|
||||
That 100 MB is already a huge savings when you consider a base image is already around 300 MB on its own. Installing Nginx with a package manager brings in a ton of dependencies, too. For something compiled from source using tools from the host, the savings can be even greater because you can choose the exact dependencies and not pull in any extra files you don’t need.
|
||||
|
||||
If you’d like to try this route, [Tom Sweeney][6] wrote a much more in-depth article, [Creating small containers with Buildah][7], which you should check out.
|
||||
|
||||
Using Buildah to build images without a full operating system and included build tools can enable much smaller images than you would otherwise be able to create. For some types of images, we can take this approach even further and create images with _only_ the application itself included.
|
||||
|
||||
### Create images with only statically linked binaries
|
||||
|
||||
Following the same philosophy that leads us to ditch administrative and build tools inside images, we can go a step further. If we specialize enough and abandon the idea of troubleshooting inside of production containers, do we need Bash? Do we need the [GNU core utilities][8]? Do we _really_ need the basic Linux filesystem? You can do this with any compiled language that allows you to create binaries with [statically linked libraries][9]—where all the libraries and functions needed by the program are copied into and stored within the binary itself.
|
||||
|
||||
This is a relatively popular way of doing things within the [Golang][10] community, so we’ll use a Go application to demonstrate.
|
||||
|
||||
The Dockerfile below takes a small Go Hello-World application and compiles it in an image `FROM golang:1.8`:
|
||||
```
|
||||
FROM golang:1.8
|
||||
|
||||
|
||||
|
||||
ENV GOOS=linux
|
||||
|
||||
ENV appdir=/go/src/gohelloworld
|
||||
|
||||
|
||||
|
||||
COPY ./ /go/src/goHelloWorld
|
||||
|
||||
WORKDIR /go/src/goHelloWorld
|
||||
|
||||
|
||||
|
||||
RUN go get
|
||||
|
||||
RUN go build -o /goHelloWorld -a
|
||||
|
||||
|
||||
|
||||
CMD ["/goHelloWorld"]
|
||||
|
||||
```
|
||||
|
||||
The resulting image, containing the binary, the source code, and the base image layer comes in at 716 MB. The only thing we actually need for our application is the compiled binary, however. Everything else is unused cruft that gets shipped around with our image.
|
||||
|
||||
If we disable `cgo` with `CGO_ENABLED=0` when we compile, we can create a binary that doesn’t wrap C libraries for some of its functions:
|
||||
```
|
||||
GOOS=linux CGO_ENABLED=0 go build -a goHelloWorld.go
|
||||
|
||||
```
|
||||
|
||||
The resulting binary can be added to an empty, or "scratch" image:
|
||||
```
|
||||
FROM scratch
|
||||
|
||||
COPY goHelloWorld /
|
||||
|
||||
CMD ["/goHelloWorld"]
|
||||
|
||||
```
|
||||
|
||||
Let’s compare the difference in image size between the two:
|
||||
```
|
||||
[ chris@krang ] $ docker images
|
||||
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
|
||||
goHello scratch a5881650d6e9 13 seconds ago 1.55 MB
|
||||
|
||||
goHello builder 980290a100db 14 seconds ago 716 MB
|
||||
|
||||
```
|
||||
|
||||
That’s a huge difference. The image built from `golang:1.8` with the `goHelloWorld` binary in it (tagged "builder" above) is _460_ times larger than the scratch image with just the binary. The entirety of the scratch image with the binary is only 1.55 MB. That means we’d be shipping around 713 MB of unnecessary data if we used the builder image.
|
||||
|
||||
As mentioned above, this method of creating small images is used often in the Golang community, and there is no shortage of blog posts on the subject. [Kelsey Hightower][11] wrote [an article on the subject][12] that goes into more detail, including dealing with dependencies other than just C libraries.
|
||||
|
||||
### Consider squashing, if it works for you
|
||||
|
||||
There’s an alternative to chaining all the commands into layers in an attempt to save space: Squashing your image. When you squash an image, you’re really exporting it, removing all the intermediate layers, and saving a single layer with the current state of the image. This has the advantage of reducing that image to a much smaller size.
|
||||
|
||||
Squashing layers used to require some creative workarounds to flatten an image—exporting the contents of a container and re-importing it as a single layer image, or using tools like `docker-squash`. Starting in version 1.13, Docker introduced a handy flag, `--squash`, to accomplish the same thing during the build process:
|
||||
```
|
||||
FROM fedora:28
|
||||
|
||||
LABEL maintainer Chris Collins <collins.christopher@gmail.com>
|
||||
|
||||
|
||||
|
||||
RUN dnf install -y nginx
|
||||
|
||||
RUN dnf clean all
|
||||
|
||||
RUN rm -rf /var/cache/yum
|
||||
|
||||
|
||||
|
||||
[chris@krang] $ docker build -t squash -f Dockerfile-squash --squash .
|
||||
|
||||
[chris@krang] $ docker images --format "{{.Repository}}: {{.Size}}" | head -n 1
|
||||
|
||||
squash: 271 MB
|
||||
|
||||
```
|
||||
|
||||
Using `docker squash` with this multi-layer Dockerfile, we end up with another 271MB image, as we did with the chained instruction example. This works great for this use case, but there’s a potential gotcha.
|
||||
|
||||
“What? ANOTHER gotcha?”
|
||||
|
||||
Well, sort of—it’s the same issue as before, causing problems in another way.
|
||||
|
||||
### Going too far: Too squashed, too small, too specialized
|
||||
|
||||
Images can share layers. The base may be _x_ megabytes in size, but it only needs to be pulled/stored once and each image can use it. The effective size of all the images sharing layers is the base layers plus the diff of each specific change on top of that. In this way, thousands of images may take up only a small amount more than a single image.
|
||||
|
||||
This is a drawback with squashing or specializing too much. When you squash an image into a single layer, you lose any opportunity to share layers with other images. Each image ends up being as large as the total size of its single layer. This might work well for you if you use only a few images and run many containers from them, but if you have many diverse images, it could end up costing you space in the long run.
|
||||
|
||||
Revisiting the Nginx squash example, we can see it’s not a big deal for this case. We end up with Fedora, Nginx installed, no cache, and squashing that is fine. Nginx by itself is not incredibly useful, though. You generally need customizations to do anything interesting—e.g., configuration files, other software packages, maybe some application code. Each of these would end up being more instructions in the Dockerfile.
|
||||
|
||||
With a traditional image build, you would have a single base image layer with Fedora, a second layer with Nginx installed (with or without cache), and then each customization would be another layer. Other images with Fedora and Nginx could share these layers.
|
||||
|
||||
Need an image:
|
||||
```
|
||||
[ App 1 Layer ( 5 MB) ] [ App 2 Layer (6 MB) ]
|
||||
|
||||
[ Nginx Layer ( 21 MB) ] ------------------^
|
||||
|
||||
[ Fedora Layer (249 MB) ]
|
||||
|
||||
```
|
||||
|
||||
But if you squash the image, then even the Fedora base layer is squashed. Any squashed image based on Fedora has to ship around its own Fedora content, adding another 249 MB for _each image!_
|
||||
```
|
||||
[ Fedora + Nginx + App 1 (275 MB)] [ Fedora + Nginx + App 2 (276 MB) ]
|
||||
|
||||
```
|
||||
|
||||
This also becomes a problem if you build lots of highly specialized, super-tiny images.
|
||||
|
||||
As with everything in life, moderation is key. Again, thanks to how layers work, you will find diminishing returns as your container images become smaller and more specialized and can no longer share base layers with other related images.
|
||||
|
||||
Images with small customizations can share base layers. As explained above, the base may be _x_ megabytes in size, but it only needs to be pulled/stored once and each image can use it. The effective size of all the images is the base layers plus the diff of each specific change on top of that. In this way, thousands of images may take up only a small amount more than a single image.
|
||||
```
|
||||
[ specific app ] [ specific app 2 ]
|
||||
|
||||
[ customizations ]--------------^
|
||||
|
||||
[ base layer ]
|
||||
|
||||
```
|
||||
|
||||
If you go too far with your image shrinking and you have too many variations or specializations, you can end up with many images, none of which share base layers and all of which take up their own space on disk.
|
||||
```
|
||||
[ specific app 1 ] [ specific app 2 ] [ specific app 3 ]
|
||||
|
||||
```
|
||||
|
||||
### Conclusion
|
||||
|
||||
There are a variety of different ways to reduce the amount of storage space and bandwidth you spend working with container images, but the most effective way is to reduce the size of the images themselves. Whether you simply clean up your caches (avoiding leaving them orphaned in intermediate layers), squash all your layers into one, or add only static binaries in an empty image, it’s worth spending some time looking at where bloat might exist in your container images and slimming them down to an efficient size.
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/7/building-container-images
|
||||
|
||||
作者:[Chris Collins][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/clcollins
|
||||
[1]:https://www.docker.com/
|
||||
[2]:https://www.nginx.com/
|
||||
[3]:https://rubyonrails.org/
|
||||
[4]:https://github.com/rbenv/rbenv
|
||||
[5]:https://opensource.com/article/18/6/getting-started-buildah
|
||||
[6]:https://twitter.com/TSweeneyRedHat
|
||||
[7]:https://opensource.com/article/18/5/containers-buildah
|
||||
[8]:https://www.gnu.org/software/coreutils/coreutils.html
|
||||
[9]:https://en.wikipedia.org/wiki/Static_library
|
||||
[10]:https://golang.org/
|
||||
[11]:https://twitter.com/kelseyhightower
|
||||
[12]:https://medium.com/@kelseyhightower/optimizing-docker-images-for-static-binaries-b5696e26eb07
|
@ -1,5 +1,5 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: translator: (LuuMing)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
@ -1,5 +1,5 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: translator: (Auk7F7)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: subject: (Arch-Wiki-Man – A Tool to Browse The Arch Wiki Pages As Linux Man Page from Offline)
|
||||
|
@ -1,5 +1,5 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: translator: (qhwdw)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
@ -1,48 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Let's get physical: How to use GPIO pins on the Raspberry Pi)
|
||||
[#]: via: (https://opensource.com/article/19/3/gpio-pins-raspberry-pi)
|
||||
[#]: author: (Anderson Silva https://opensource.com/users/ansilva)
|
||||
|
||||
Let's get physical: How to use GPIO pins on the Raspberry Pi
|
||||
======
|
||||
The 10th article in our series on getting started with Raspberry Pi explains how the GPIO pins work.
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/raspbery_pi_zero_wireless_hardware.jpg?itok=9YFzdxFQ)
|
||||
|
||||
Until now, this series has focused on the Raspberry Pi's software side, but today we'll get into the hardware. The availability of [general-purpose input/output][1] (GPIO) pins was one of the main features that interested me in the Pi when it first came out. GPIO allows you to programmatically interact with the physical world by attaching sensors, relays, and other types of circuitry to the Raspberry Pi.
|
||||
|
||||
![](https://opensource.com/sites/default/files/uploads/raspberrypi_10_gpio-pins-pi2.jpg)
|
||||
|
||||
Each pin on the board either has a predefined function or is designated as general purpose. Also, different Raspberry Pi models have either 26 or 40 pins for you to use at your discretion. Wikipedia has a [good overview of each pin][2] and its functionality.
|
||||
|
||||
You can do many things with the Pi's GPIO pins. I've written some other articles about using the GPIOs, including a trio of articles ([Part I][3], [Part II][4], and [Part III][5]) about controlling holiday lights with the Raspberry Pi while using open source software to pair the lights with music.
|
||||
|
||||
The Raspberry Pi community has done a great job in creating libraries in different programming languages, so you should be able to interact with the pins using [C][6], [Python][7], [Scratch][8], and other languages.
|
||||
|
||||
Also, if you want the ultimate experience to interact with the physical world, pick up a [Raspberry Pi Sense Hat][9]. It is an affordable expansion board for the Pi that plugs into the GPIO pins so you can programmatically interact with LEDs, joysticks, and barometric pressure, temperature, humidity, gyroscope, accelerometer, and magnetometer sensors.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/3/gpio-pins-raspberry-pi
|
||||
|
||||
作者:[Anderson Silva][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/ansilva
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.raspberrypi.org/documentation/usage/gpio/
|
||||
[2]: https://en.wikipedia.org/wiki/Raspberry_Pi#General_purpose_input-output_(GPIO)_connector
|
||||
[3]: https://opensource.com/life/15/2/music-light-show-with-raspberry-pi
|
||||
[4]: https://opensource.com/life/15/12/ssh-your-christmas-tree-raspberry-pi
|
||||
[5]: https://opensource.com/article/18/12/lightshowpi-raspberry-pi
|
||||
[6]: https://www.bigmessowires.com/2018/05/26/raspberry-pi-gpio-programming-in-c/
|
||||
[7]: https://www.raspberrypi.org/documentation/usage/gpio/python/README.md
|
||||
[8]: https://www.raspberrypi.org/documentation/usage/gpio/scratch2/README.md
|
||||
[9]: https://opensource.com/life/16/4/experimenting-raspberry-pi-sense-hat
|
@ -1,62 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (hopefully2333)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Learn about computer security with the Raspberry Pi and Kali Linux)
|
||||
[#]: via: (https://opensource.com/article/19/3/computer-security-raspberry-pi)
|
||||
[#]: author: (Anderson Silva https://opensource.com/users/ansilva)
|
||||
|
||||
Learn about computer security with the Raspberry Pi and Kali Linux
|
||||
======
|
||||
Raspberry Pi is a great way to learn about computer security. Learn how in the 11th article in our getting-started series.
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/security_privacy_lock.png?itok=ZWjrpFzx)
|
||||
|
||||
Is there a hotter topic in technology than securing your computer? Some experts will tell you that there is no such thing as perfect security. They joke that if you want your server or application to be truly secure, then turn off your server, unplug it from the network, and put it in a safe somewhere. The problem with that should be obvious: What good is an app or server that nobody can use?
|
||||
|
||||
That's the conundrum around security. How can we make something secure enough and still usable and valuable? I am not a security expert by any means, although I hope to be one day. With that in mind, I thought it would make sense to share some ideas about what you can do with a Raspberry Pi to learn more about security.
|
||||
|
||||
I should note that, like the other articles in this series dedicated to Raspberry Pi beginners, my goal is not to dive in deep, rather to light a fire of interest for you to learn more about these topics.
|
||||
|
||||
### Kali Linux
|
||||
|
||||
When it comes to "doing security things," one of the Linux distributions that comes to mind is [Kali Linux][1]. Kali's development is primarily focused on forensics and penetration testing. It has more than 600 preinstalled [penetration-testing programs][2] to test your computer's security, and a [forensics mode][3], which prevents it from touching the internal hard drive or swap space of the system being examined.
|
||||
|
||||
![](https://opensource.com/sites/default/files/uploads/raspberrypi_11_kali.png)
|
||||
|
||||
Like Raspbian, Kali Linux is based on the Debian distribution, and you can find directions on installing it on the Raspberry Pi in its main [documentation portal][4]. If you installed Raspbian or another Linux distribution on your Raspberry Pi, you should have no problem installing Kali. Kali Linux's creators have even put together [training, workshops, and certifications][5] to help boost your career in the security field.
|
||||
|
||||
### Other Linux distros
|
||||
|
||||
Most standard Linux distributions, like Raspbian, Ubuntu, and Fedora, also have [many security tools available][6] in their repositories. Some great tools to explore include [Nmap][7], [Wireshark][8], [auditctl][9], and [SELinux][10].
|
||||
|
||||
### Projects
|
||||
|
||||
There are many other security-related projects you can run on your Raspberry Pi, such as [Honeypots][11], [Ad blockers][12], and [USB sanitizers][13]. Take some time and learn about them!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/3/computer-security-raspberry-pi
|
||||
|
||||
作者:[Anderson Silva][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/ansilva
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.kali.org/
|
||||
[2]: https://en.wikipedia.org/wiki/Kali_Linux#Development
|
||||
[3]: https://docs.kali.org/general-use/kali-linux-forensics-mode
|
||||
[4]: https://docs.kali.org/kali-on-arm/install-kali-linux-arm-raspberry-pi
|
||||
[5]: https://www.kali.org/penetration-testing-with-kali-linux/
|
||||
[6]: https://linuxblog.darkduck.com/2019/02/9-best-linux-based-security-tools.html
|
||||
[7]: https://nmap.org/
|
||||
[8]: https://www.wireshark.org/
|
||||
[9]: https://linux.die.net/man/8/auditctl
|
||||
[10]: https://opensource.com/article/18/7/sysadmin-guide-selinux
|
||||
[11]: https://trustfoundry.net/honeypi-easy-honeypot-raspberry-pi/
|
||||
[12]: https://pi-hole.net/
|
||||
[13]: https://www.circl.lu/projects/CIRCLean/
|
@ -1,235 +0,0 @@
|
||||
Python ChatOps 库: Opsdroid 和 Errbot
|
||||
======
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/idea_innovation_mobile_phone.png?itok=RqVtvxkd)
|
||||
这篇文章由笔者和 [Lacey Williams Henschel][1] 共同编写。
|
||||
|
||||
ChatOps 是基于会话导向而进行的开发。它的想法是你可以编写能够对聊天窗口中的某些输入进行回复的可执行代码。作为一个开发者,你能够用 ChatOps 从 Slack 合并拉取请求,自动从收到的 Facebook 消息中给某人分配支持票或者通过 IRC 检查开发状态。
|
||||
|
||||
在 Python 世界,最为广泛使用的 ChatOps 库是 Opsdroid 和 Errbot。在这个月的 Python 专栏,让我们一起聊聊使用它们是怎样的体验,它们各自适用于什么方面以及如何着手使用它们。
|
||||
|
||||
### Opsdroid
|
||||
|
||||
[Opsdroid][2] 是一个相对年轻的(始于 2016)Python 开源聊天机器人库。它有着良好的开发文档,不错的教程并且包含能够帮助你对接流行的聊天服务的插件。
|
||||
|
||||
#### 它内建了什么
|
||||
|
||||
库本身并没有自带所有你需要上手的东西,但这是故意的。轻量级的框架鼓励你去运用它现存的连接器(Opsdroid 所谓的帮你接入聊天服务的插件)或者去编写你自己的,但是它并不会因自带你所不需要的的连接器而自贬身价。你可以轻松使用现有的 Opsdroid 连接器来接入:
|
||||
|
||||
+ 命令行
|
||||
+ Cisco Spark
|
||||
+ Facebook
|
||||
+ GitHub
|
||||
+ Matrix
|
||||
+ Slack
|
||||
+ Telegram
|
||||
+ Twitter
|
||||
+ Websockets
|
||||
|
||||
Opsdroid 引用使聊天机器人能够展现它们的技能的函数。这些技能其实是 `异步` Python 函数并使用 Opsdroid 叫做“匹配器”的匹配装饰器。你可以设置你的 Opsdroid 项目,来使用同样从你设置文件所在的代码基地来的技能。你也可以从外面的公共或私人仓库调用这些技能。
|
||||
|
||||
你同样可以激活一些现存的 Opsdroid 技能包括 [seen][3],它会告诉你什么时候一个特定用户被聊天机器人所看到以及 [weather][4],会将天气报告给用户。
|
||||
|
||||
最后,Opdroid 允许你使用现存的数据库模块设置数据库。现在 Opdroid 支持的数据库包括:
|
||||
|
||||
+ Mongo
|
||||
+ Redis
|
||||
+ SQLite
|
||||
|
||||
你可以在你的 Opdroid 项目中的 `configuration.yaml` 文件设置数据库、技能和连接器。
|
||||
|
||||
#### Opsdroid 的优势
|
||||
|
||||
**Docker 支持:**从一开始 Opsdroid 就打算在 Docker 中良好运行。Docker 指导是它 [安装文档][5] 中的一部分。使用 Opsdroid 和 Docker Copmose 也很简单:将 Opsdroid 设置成一种服务,当你运行 `docker-compose up` 时,你的 Opsdroid 服务将会开启你的聊天机器人也将就绪。
|
||||
```
|
||||
version: "3"
|
||||
|
||||
|
||||
|
||||
services:
|
||||
|
||||
opsdroid:
|
||||
|
||||
container_name: opsdroid
|
||||
|
||||
build:
|
||||
|
||||
context: .
|
||||
|
||||
dockerfile: Dockerfile
|
||||
|
||||
```
|
||||
|
||||
**丰富的连接器:** Opsdroid 支持九种从外部接入像 Slack 和 Github 等服务的连接器。你所要做的一切就是在你的设置文件中激活那些连接器然后把必须的口令或者 API 密匙传过去。比如为了激活 Opsdroid 以在一个叫做 `#updates` 的 Slack 频道发帖,你需要将以下代码加入你设置文件的 `connectors` 部分:
|
||||
```
|
||||
- name: slack
|
||||
|
||||
api-token: "this-is-my-token"
|
||||
|
||||
default-room: "#updates"
|
||||
|
||||
```
|
||||
|
||||
在设置 Opsdroid 以接入 Slack 之前你需要[添加一个机器人用户][6]。
|
||||
|
||||
如果你需要接入一个 Opsdroid 不支持的服务,在[文档][7]里有有添加你自己的连接器的教程。
|
||||
|
||||
**相当不错的文档:** 特别是对于一个在积极开发中的新兴库来说,Opsdroid 的文档十分有帮助。这些文档包括一篇带你创建几个不同的基本技能的[教程][8]。Opsdroid 在[技能][9],[连接器][7],[数据库][10],以及[匹配器][11]方面的文档也十分清晰。
|
||||
|
||||
**自然语言处理:**它所支持的技能和连接器的仓库为它的技能提供了富有帮助的示范代码。它同样提供了几个包括 [Dialogflow][12],[luis.ai][13],[Recast.AI][14] 以及 [wit.ai][15] 的 NLP API。
|
||||
|
||||
#### 对 Opsdroid 可能的考虑
|
||||
|
||||
Opsdroid 对它的一部分连接器还没有激活全部的特性。比如说,Slack API 允许你向你的消息添加颜色柱,图片以及其他的“附件”。Opsdroid Slack 连接器并没有激活“附件”特性,所以如果那些特性对你来说很重要的话,你需要编写一个自定义的 Slack 连接器。如果连接器缺少一个你需要的特性,Opsdroid 将欢迎你的[贡献][16]。文档中可以使用更多的例子,特别是对于预料到的使用场景。
|
||||
|
||||
#### 示例用法
|
||||
|
||||
`hello/__init__.py`
|
||||
```
|
||||
from opsdroid.matchers import match_regex
|
||||
|
||||
import random
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@match_regex(r'hi|hello|hey|hallo')
|
||||
|
||||
async def hello(opsdroid, config, message):
|
||||
|
||||
text = random.choice(["Hi {}", "Hello {}", "Hey {}"]).format(message.user)
|
||||
|
||||
await message.respond(text)
|
||||
|
||||
```
|
||||
|
||||
`configuration.yaml`
|
||||
```
|
||||
connectors:
|
||||
|
||||
- name: websocket
|
||||
|
||||
|
||||
|
||||
skills:
|
||||
|
||||
|
||||
|
||||
- name: hello
|
||||
|
||||
repo: "https://github.com/<user_id>/hello-skill"
|
||||
|
||||
```
|
||||
|
||||
### Errbot
|
||||
|
||||
[Errbot][17] 是一个功能齐全的开源聊天机器人。Errbot 发行于2012年并且拥有人们从一个成熟的项目能期待的一切,包括良好的文档,优秀的教程以及许多帮你连入现存的流行聊天服务的插件。
|
||||
|
||||
#### 它内建了什么
|
||||
|
||||
不像采用了一个较轻量级途径的 Opsdroid,Errbot 安全地自带了你需要创建一个自定义机器人的一切东西。
|
||||
|
||||
Errbot 包括了对于本地 XMPP, IRC, Slack, Hipchat 以及 Telegram 服务的支持。它通过社区支持的后端列出了另外十种服务。
|
||||
|
||||
#### Errbot 的优势
|
||||
|
||||
**良好的文档:** Errbot 的文档成熟易读。
|
||||
|
||||
**动态插件架构:** Errbot 允许你通过和聊天机器人交谈安全安装,卸载,更新,激活以及禁用插件。这使得开发和添加特性十分简便。感谢 Errbot 的颗粒性授权系统,出于安全意识这所有的一切都可以被锁闭。
|
||||
|
||||
当某个人输入 `!help`,Errbot 使用你的插件文档字符串来为可获取的命令生成文档,这使得了解每行命令的作用更加简便。
|
||||
|
||||
**內建的管理和安全特性:** Errbot 允许你限制拥有管理员权限甚至细粒度访问控制用户列表。比如说你可以限制特定用户或房间访问特定命令。
|
||||
|
||||
**额外的插件框架:** Errbot 支持钩子,回调,子命令,webhook,轮询以及其它[多得多的特性][18]。如果那些还不够,你甚至可以编写[动态插件][19]。当你需要基于在远程服务器上什么命令可以获取来激活聊天命令时,这个特性十分有用。
|
||||
|
||||
**自带测试框架:** Errbot 支持 [pytest][20] 同时也自带一些能使测试插件变的可能且简便的有用设施。它“[测试你的插件][21]”的文档出于深思熟虑并提供足够的资料让你上手。
|
||||
|
||||
#### 对 Errbot 可能的考虑
|
||||
|
||||
**首先 !:** 默认情况下,Errbot 命令发出时以一个惊叹号打头(`!help` 以及 `!hello`)。一些人可能会喜欢这样,但是另一些人可能认为这让人烦恼。谢天谢地,这很容易关掉。
|
||||
|
||||
**插件元数据** 首先,Errbot 的 [Hello World][22] 插件示例看上去易于使用。然而我无法加载我的插件直到我进一步阅读了教程并发现我还需要一个 `.plug` 文档,一个 Errbot 用来加载插件的文档。这可能比较吹毛求疵了,但是在我深挖文档之前,这对我来说都不是显而易见的。
|
||||
|
||||
### 示例用法
|
||||
|
||||
`hello.py`
|
||||
```
|
||||
import random
|
||||
|
||||
from errbot import BotPlugin, botcmd
|
||||
|
||||
|
||||
|
||||
class Hello(BotPlugin):
|
||||
|
||||
|
||||
|
||||
@botcmd
|
||||
|
||||
def hello(self, msg, args):
|
||||
|
||||
text = random.choice(["Hi {}", "Hello {}", "Hey {}"]).format(message.user)
|
||||
|
||||
return text
|
||||
|
||||
```
|
||||
|
||||
`hello.plug`
|
||||
```
|
||||
[Core]
|
||||
|
||||
Name = Hello
|
||||
|
||||
Module = hello
|
||||
|
||||
|
||||
|
||||
[Python]
|
||||
|
||||
Version = 2+
|
||||
|
||||
|
||||
|
||||
[Documentation]
|
||||
|
||||
Description = Example "Hello" plugin
|
||||
|
||||
```
|
||||
|
||||
你用过 Errbot 或 Opsdroid 吗?如果用过请留下关于你对于这些工具印象的留言。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/3/python-chatops-libraries-opsdroid-and-errbot
|
||||
|
||||
作者:[Jeff Triplett][a]
|
||||
译者:[tomjlw](https://github.com/tomjlw)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/laceynwilliams
|
||||
[1]:https://opensource.com/users/laceynwilliams
|
||||
[2]:https://opsdroid.github.io/
|
||||
[3]:https://github.com/opsdroid/skill-seen
|
||||
[4]:https://github.com/opsdroid/skill-weather
|
||||
[5]:https://opsdroid.readthedocs.io/en/stable/#docker
|
||||
[6]:https://api.slack.com/bot-users
|
||||
[7]:https://opsdroid.readthedocs.io/en/stable/extending/connectors/
|
||||
[8]:https://opsdroid.readthedocs.io/en/stable/tutorials/introduction/
|
||||
[9]:https://opsdroid.readthedocs.io/en/stable/extending/skills/
|
||||
[10]:https://opsdroid.readthedocs.io/en/stable/extending/databases/
|
||||
[11]:https://opsdroid.readthedocs.io/en/stable/matchers/overview/
|
||||
[12]:https://opsdroid.readthedocs.io/en/stable/matchers/dialogflow/
|
||||
[13]:https://opsdroid.readthedocs.io/en/stable/matchers/luis.ai/
|
||||
[14]:https://opsdroid.readthedocs.io/en/stable/matchers/recast.ai/
|
||||
[15]:https://opsdroid.readthedocs.io/en/stable/matchers/wit.ai/
|
||||
[16]:https://opsdroid.readthedocs.io/en/stable/contributing/
|
||||
[17]:http://errbot.io/en/latest/
|
||||
[18]:http://errbot.io/en/latest/features.html#extensive-plugin-framework
|
||||
[19]:http://errbot.io/en/latest/user_guide/plugin_development/dynaplugs.html
|
||||
[20]:http://pytest.org/
|
||||
[21]:http://errbot.io/en/latest/user_guide/plugin_development/testing.html
|
||||
[22]:http://errbot.io/en/latest/index.html#simple-to-build-upon
|
356
translated/tech/20180719 Building tiny container images.md
Normal file
356
translated/tech/20180719 Building tiny container images.md
Normal file
@ -0,0 +1,356 @@
|
||||
如何打造更小巧的容器镜像
|
||||
======
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/containers_scale_performance.jpg?itok=R7jyMeQf)
|
||||
|
||||
[Docker][1] 近几年的爆炸性发展让大家逐渐了解到容器和容器镜像的概念。尽管 Linux 容器技术在很早之前就已经出现,这项技术近来的蓬勃发展却还是要归功于 Docker 对用户友好的命令行界面以及使用 Dockerfile 轻松构建镜像的方式。纵然 Docker 大大降低了入门容器技术的难度,但构建一个兼具功能强大、体积小巧的容器镜像的过程中,有很多技巧需要了解。
|
||||
|
||||
### 清理不必要的文件
|
||||
|
||||
这一步和在普通服务器上清理文件没有太大的区别,而且要清理得更加仔细。一个小体积的容器镜像在传输方面有很大的优势,同时,在磁盘上存储大量不必要的数据也是对资源的一种浪费。这个原则对于所有服务器来说都是合适的。
|
||||
|
||||
清理容器镜像中的缓存文件可以有效缩小镜像体积。下面的对比是分别使用 `dnf` 安装 [Nginx][2] 构建的镜像和使用 `yum` 安装 Nginx 后清理缓存文件构建的镜像:
|
||||
```
|
||||
# Dockerfile with cache
|
||||
|
||||
FROM fedora:28
|
||||
|
||||
LABEL maintainer Chris Collins <collins.christopher@gmail.com>
|
||||
|
||||
|
||||
|
||||
RUN dnf install -y nginx
|
||||
|
||||
|
||||
|
||||
-----
|
||||
|
||||
|
||||
|
||||
# Dockerfile w/o cache
|
||||
|
||||
FROM fedora:28
|
||||
|
||||
LABEL maintainer Chris Collins <collins.christopher@gmail.com>
|
||||
|
||||
|
||||
|
||||
RUN dnf install -y nginx \
|
||||
|
||||
&& dnf clean all \
|
||||
|
||||
&& rm -rf /var/cache/yum
|
||||
|
||||
|
||||
|
||||
-----
|
||||
|
||||
|
||||
|
||||
[chris@krang] $ docker build -t cache -f Dockerfile .
|
||||
|
||||
[chris@krang] $ docker images --format "{{.Repository}}: {{.Size}}"
|
||||
|
||||
| head -n 1
|
||||
|
||||
cache: 464 MB
|
||||
|
||||
|
||||
|
||||
[chris@krang] $ docker build -t no-cache -f Dockerfile-wo-cache .
|
||||
|
||||
[chris@krang] $ docker images --format "{{.Repository}}: {{.Size}}" | head -n 1
|
||||
|
||||
no-cache: 271 MB
|
||||
|
||||
```
|
||||
|
||||
从上面的结果来看,清理缓存文件的效果相当显著。和清除了 `yum` 缓存文件的容器镜像相比,不清除 `dnf` 缓存文件构建出来的容器镜像体积接近前者的两倍。除此以外,包管理器缓存文件、Ruby gem 临时文件、`nodejs` 缓存文件,甚至是下载的源码 tarball 最好都全部清理掉。
|
||||
|
||||
### 层:一个潜在的隐患
|
||||
|
||||
很不幸(当你往下读,你会发现这是不幸中的万幸),根据容器层的概念,不能简单地向 Dockerfile 中写一句 `RUN rm -rf /var/cache/yum` 就完事儿了。因为 Dockerfile 的每一条命令都以一个层的形式存储,并一层层地叠加。所以,如果你是这样写的:
|
||||
```
|
||||
RUN dnf install -y nginx
|
||||
|
||||
RUN dnf clean all
|
||||
|
||||
RUN rm -rf /var/cache/yum
|
||||
|
||||
```
|
||||
|
||||
你的容器镜像就会包含三层,而 `RUN dnf install -y nginx` 这一层仍然会保留着那些缓存文件,然后在另外两层中被移除,但缓存仍然是存在的,只是你在最终的容器镜像中见不到它们而已。
|
||||
|
||||
在上一节的示例中,你会看到正确的做法是将几条命令连接起来,在产生缓存文件的同一层里把缓存文件清理掉:
|
||||
```
|
||||
RUN dnf install -y nginx \
|
||||
|
||||
&& dnf clean all \
|
||||
|
||||
&& rm -rf /var/cache/yum
|
||||
|
||||
```
|
||||
|
||||
这样就把几条命令连成了一条命令,在最终的镜像中只占用一个层。这样只会稍微多耗费一点点构建容器镜像的时间,但被清理掉的缓存文件就不会留存在最终的镜像中了。这是一个很好的折中方法,只需要把一些相关的命令(例如 `yum install` 和 `yum clean all`、下载文件、解压文件、移除 tarball 等等)连接成一个命令,就可以在最终的容器镜像中节省出大量体积,Docker 层也能更好地发挥作用。
|
||||
|
||||
层还有一个更隐蔽的特性。每一层都记录了文件的更改,这里的更改并不仅仅指文件是否存在、文件内容是否被改动,而是包括文件属性在内的所有更改。因此即使是对文件使用了 `chmod` 操作也会被记录在层中。
|
||||
|
||||
下面是一次 `docker images` 命令的输出内容。其中容器镜像 `layer_test_1` 是仅在 CentOS 基础镜像中增加了一个 1GB 大小的文件后构建出来的镜像,而容器镜像 `layer_test_2` 是使用了 `FROM layer_test_1` 语句,仅仅再执行一条 `chmod u+x` 命令后构建出来的镜像。
|
||||
```
|
||||
layer_test_2 latest e11b5e58e2fc 7 seconds ago 2.35 GB
|
||||
|
||||
layer_test_1 latest 6eca792a4ebe 2 minutes ago 1.27 GB
|
||||
|
||||
```
|
||||
|
||||
如你所见,`layer_test_2` 镜像比 `layer_test_1` 镜像大了 1GB 以上。尽管 `layer_test_2` 基于 `layer_test_1` 且只比 `layer_test_1` 多出一层,但恰好就在这多出来的一层中包含了一个额外的 1GB 的文件。在构建容器镜像的过程中,如果在单独一层中进行移动、更改、删除文件,都会出现类似的结果。
|
||||
|
||||
### 专用镜像和公用镜像
|
||||
|
||||
就有这么一个亲身经历:我们的项目重度依赖于 [Ruby on Rails][3],于是我们开始使用容器。一开始我们就建立了一个 Ruby 的基础镜像供所有的团队使用,为了简单起见(实际上这样并不好),我们使用 [rbenv][4] 将 Ruby 最新的 4 个版本都安装到了这个镜像当中,目的是让开发人员只用这个镜像就可以将使用不同版本 Ruby 的应用程序迁移到容器中。我们当时还认为这是一个有点大但兼容性相当好的镜像,因为这个镜像可以同时满足各个团队的使用。
|
||||
|
||||
实际上这是费力不讨好的。如果将不同版本应用程序安装在独立的镜像中,可以很轻松地实现镜像的自动化维护。同时,还可以在应用程序接近生命周期结束前提前做好预防措施,以免产生不可控的后果。庞大的公用镜像也会对资源造成浪费,当我们后来将这个庞大的镜像按照 Ruby 版本进行拆分之后,每个基于这些基础镜像构建出来的应用镜像体积都会比原来缩小很多,节省了大量的服务器存储资源。
|
||||
|
||||
这个例子也不是说不能追求镜像的兼容性,但仅对于这个例子来说,分拆成多个小的专用镜像无疑能够节省存储资源和维护成本,同时不同的团队也能够根据特定的需求来做定制化的配置。
|
||||
|
||||
### 从零开始:将你需要的内容添加到空白镜像中
|
||||
|
||||
有一些和 Dockerfile 一样易用的工具可以轻松创建非常小的兼容 Docker 的容器镜像,这些镜像甚至不需要包含一个完整的操作系统。
|
||||
|
||||
我曾经写过一篇[关于 Buildah 的文章][5],我想在这里再一次安利这个工具。它可以使用宿主机上的工具来操作一个空白镜像并安装打包好的应用程序,而且这些工具不会被包含到镜像当中。
|
||||
|
||||
Buildah 取代了 `docker build` 命令。可以使用 Buildah 将容器的文件系统挂载到宿主机上并进行交互。
|
||||
|
||||
下面来使用 Buildah 实现上文中 Nginx 的例子:
|
||||
```
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -o errexit
|
||||
|
||||
|
||||
|
||||
# Create a container
|
||||
|
||||
container=$(buildah from scratch)
|
||||
|
||||
|
||||
|
||||
# Mount the container filesystem
|
||||
|
||||
mountpoint=$(buildah mount $container)
|
||||
|
||||
|
||||
|
||||
# Install a basic filesystem and minimal set of packages, and nginx
|
||||
|
||||
dnf install --installroot $mountpoint --releasever 28 glibc-minimal-langpack nginx --setopt install_weak_deps=false -y
|
||||
|
||||
|
||||
|
||||
# Save the container to an image
|
||||
|
||||
buildah commit --format docker $container nginx
|
||||
|
||||
|
||||
|
||||
# Cleanup
|
||||
|
||||
buildah unmount $container
|
||||
|
||||
|
||||
|
||||
# Push the image to the Docker daemon’s storage
|
||||
|
||||
buildah push nginx:latest docker-daemon:nginx:latest
|
||||
|
||||
```
|
||||
|
||||
你会发现这里使用的已经不是 Dockerfile 了,而是普通的 Bash 脚本,而且是从空白镜像开始构建的。上面这段 Bash 脚本将容器的根文件系统挂载到了宿主机上,然后使用宿主机的命令来安装及应用程序,这样的话就不需要把软件包管理器放置到容器镜像中了。
|
||||
|
||||
这样所有无关的内容(例如 `dnf`)就不再会包含在镜像中了。在这个例子当中,构建出来的镜像大小只有 304 MB,比使用 Dockerfile 构建的镜像减少了 100 MB 以上。
|
||||
```
|
||||
[chris@krang] $ docker images |grep nginx
|
||||
|
||||
docker.io/nginx buildah 2505d3597457 4 minutes ago 304 MB
|
||||
|
||||
```
|
||||
|
||||
_注:这个镜像是使用上面的构建脚本构建的,镜像名称中的 `docker.io` 只是在推送到镜像仓库时人为加上的。_
|
||||
|
||||
对于一个 300MB 级别的容器镜像来说,能缩小 100MB 已经是很显著的节省了。使用软件包管理器来安装 Nginx 会带来大量的依赖项,如果能够使用宿主机直接从源代码对应用程序进行编译然后构建到容器镜像中,节省出来的空间还可以更多,因为这个时候可以精细的选用必要的依赖项,非必要的依赖项一概不构建到镜像中。
|
||||
|
||||
[Tom Sweeney][6] 有一篇文章《[用 Buildah 构建更小的容器][7]》,如果你想在这方面做深入的优化,不妨参考一下。
|
||||
|
||||
通过 Buildah 可以构建一个不包含完整操作系统和代码编译工具的容器镜像,大幅缩减了容器镜像的体积。因此可以采用这种方式,创建一个只包含应用程序本身的镜像。
|
||||
|
||||
### 使用静态链接的二进制文件来构建镜像
|
||||
|
||||
按照这个思路,我们甚至可以舍弃容器内部的管理工具。例如,如果我们不需要在容器中进行调试,是不是可以不要 Bash 了?是不是可以不要 [GNU 套件][8]了?是不是可以不要 Linux 基础文件系统了?如果你使用的编译型语言支持[静态链接库][9],将应用程序所需要的所有库和函数都编译成二进制文件,那么上面那些“累赘”可以统统省去。
|
||||
|
||||
这种做法在 [Golang][10] 社区中已经十分常见,下面我们使用由 Go 语言编写的应用程序进行展示:
|
||||
|
||||
以下这个 Dockerfile 基于 `golang:1.8` 构建一个 Hello World 应用程序镜像:
|
||||
```
|
||||
FROM golang:1.8
|
||||
|
||||
|
||||
|
||||
ENV GOOS=linux
|
||||
|
||||
ENV appdir=/go/src/gohelloworld
|
||||
|
||||
|
||||
|
||||
COPY ./ /go/src/goHelloWorld
|
||||
|
||||
WORKDIR /go/src/goHelloWorld
|
||||
|
||||
|
||||
|
||||
RUN go get
|
||||
|
||||
RUN go build -o /goHelloWorld -a
|
||||
|
||||
|
||||
|
||||
CMD ["/goHelloWorld"]
|
||||
|
||||
```
|
||||
|
||||
构建出来的镜像中包含了二进制文件、源代码以及基础镜像层,一共 716MB。但对于应用程序运行唯一必要的只有编译后的二进制文件,其余内容在镜像中都是多余的。
|
||||
|
||||
如果在编译的时候通过指定参数 `CGO_ENABLED=0` 来禁用 `cgo`,就可以在编译二进制文件的时候忽略某些 C 语言库:
|
||||
```
|
||||
GOOS=linux CGO_ENABLED=0 go build -a goHelloWorld.go
|
||||
```
|
||||
|
||||
编译出来的二进制文件可以基于空白镜像来构建应用程序镜像:
|
||||
```
|
||||
FROM scratch
|
||||
|
||||
COPY goHelloWorld /
|
||||
|
||||
CMD ["/goHelloWorld"]
|
||||
|
||||
```
|
||||
|
||||
来看一下两次构建的镜像对比:
|
||||
```
|
||||
[ chris@krang ] $ docker images
|
||||
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
|
||||
goHello scratch a5881650d6e9 13 seconds ago 1.55 MB
|
||||
|
||||
goHello builder 980290a100db 14 seconds ago 716 MB
|
||||
|
||||
```
|
||||
|
||||
从镜像体积来说简直是天差地别了。基于 `golang:1.8` 镜像构建出来的应用程序镜像(带有 builder 标签)体积是基于空白镜像构建出来的应用程序镜像的 460 倍!后者的整个镜像大小只有 1.55MB,也就是说,有 713MB 的数据都是非必要的。
|
||||
|
||||
正如上面提到的,这种缩减镜像体积的方式在 Golang 社区非常流行,因此不乏这方面的文章。[Kelsey Hightower][11] 有一篇[文章][12]专门介绍了如何处理这些库的依赖关系。
|
||||
|
||||
### 压缩镜像层
|
||||
|
||||
除了前面几节中讲到的将多个命令连接成一个命令的技巧,还可以对镜像层进行压缩。镜像层压缩的实质是删除掉镜像构建过程中的所有中间层,然后使用镜像的当前状态导出单个镜像层。这样可以进一步将镜像缩小到更小的体积。
|
||||
|
||||
在 Docker 1.13 之前,压缩镜像层的的过程可能比较麻烦,需要用到 `docker-squash` 之类的工具来导出容器的内容并重新导入成一个单层的镜像。但 Docker 在 Docker 1.13 中引入了 `--squash` 参数,可以在构建过程中实现同样的功能:
|
||||
```
|
||||
FROM fedora:28
|
||||
|
||||
LABEL maintainer Chris Collins <collins.christopher@gmail.com>
|
||||
|
||||
|
||||
|
||||
RUN dnf install -y nginx
|
||||
|
||||
RUN dnf clean all
|
||||
|
||||
RUN rm -rf /var/cache/yum
|
||||
|
||||
|
||||
|
||||
[chris@krang] $ docker build -t squash -f Dockerfile-squash --squash .
|
||||
|
||||
[chris@krang] $ docker images --format "{{.Repository}}: {{.Size}}" | head -n 1
|
||||
|
||||
squash: 271 MB
|
||||
|
||||
```
|
||||
|
||||
通过这种方式使用 Dockerfile 构建出来的镜像有 271MB 大小,和上面连接多条命令的方案构建出来的镜像体积一样,因此这个方案也是有效的,但也有一个潜在的问题,而且是另一种问题。
|
||||
|
||||
### Going too far: Too squashed, too small, too specialized
|
||||
|
||||
容器镜像之间可以共享镜像层。一个镜像层本身会带有一定的体积,但只要存在于镜像仓库中,就可以被其它容器镜像复用。一个容器镜像的大小是基础镜像层加上每层的差异内容,因此,如果有数千个基于同一个基础镜像的容器镜像,其体积之和也有可能只比一个基础镜像大不了多少。
|
||||
|
||||
因此,如果过度使用压缩图像层的方案,将不同镜像压缩成单个镜像层,各个容器镜像之间就没有可以共享的镜像层了,每个容器镜像都会占有单独的体积。如果你只需要维护少数几个容器镜像,这个问题可以忽略不计;但如果你要维护的容器镜像很多,从长远来看,就会耗费大量的存储空间。
|
||||
|
||||
回顾上面 Nginx 的例子。在这个镜像中,有 Fedora 操作系统和 Nginx 应用程序,没有安装缓存,并且已经被压缩。但我们一般不会使用一个原始的 Nginx,而是会修改配置文件,以及引入其它代码或应用程序来配合 Nginx 使用,而要做到这些,Dockerfile 就变得更加复杂了。
|
||||
|
||||
如果使用普通的镜像构建方式,构建出来的容器镜像就会带有 Fedora 操作系统的镜像层、一个安装了 Nginx 的镜像层、为 Nginx 作自定义配置的其它多个镜像层,而如果有其它容器镜像需要用到 Fedora 或者 Nginx,就可以复用这个容器镜像的前两层。
|
||||
|
||||
```
|
||||
[ App 1 Layer ( 5 MB) ] [ App 2 Layer (6 MB) ]
|
||||
|
||||
[ Nginx Layer ( 21 MB) ] ------------------^
|
||||
|
||||
[ Fedora Layer (249 MB) ]
|
||||
|
||||
```
|
||||
|
||||
如果使用压缩镜像层的构建方式,Fedora 操作系统会和 Nginx 以及其它配置内容都被压缩到同一层里面,如果有其它容器镜像需要使用到 Fedora,就必须重新引入 Fedora 基础镜像,这样每个容器镜像都会额外增加 249MB 的大小。
|
||||
```
|
||||
[ Fedora + Nginx + App 1 (275 MB)] [ Fedora + Nginx + App 2 (276 MB) ]
|
||||
|
||||
```
|
||||
|
||||
当你构建了大量在功能上趋于分化的的小型容器镜像是,这个问题就会暴露出来了。
|
||||
|
||||
就像生活中的每一件事一样,关键是要做到适度。根据镜像层的实现原理,如果一个容器镜像变得越小、越专用化,就越难和其它容器镜像共享基础的镜像层,这样反而带来不好的效果。
|
||||
|
||||
对于仅在基础镜像上做微小变动构建出来的多个容器镜像,可以考虑共享基础镜像层。如上所述,一个镜像层本身会带有一定的体积,但只要存在于镜像仓库中,就可以被其它容器镜像复用。
|
||||
```
|
||||
[ specific app ] [ specific app 2 ]
|
||||
|
||||
[ customizations ]--------------^
|
||||
|
||||
[ base layer ]
|
||||
|
||||
```
|
||||
|
||||
一个容器镜像变得越小、越专用化,就越难和其它容器镜像共享基础的镜像层,最终会不必要地占用越来越多的存储空间。
|
||||
```
|
||||
[ specific app 1 ] [ specific app 2 ] [ specific app 3 ]
|
||||
|
||||
```
|
||||
|
||||
### 总结
|
||||
|
||||
减少处理容器镜像时所需的存储空间和带宽的方法有很多,其中最直接的方法就是减小容器镜像本身的大小。在使用容器的过程中,要经常留意容器镜像是否体积过大,根据不同的情况采用上述提到的清理缓存、压缩层、在空白镜像中放入二进制文件等不同的方法,将容器镜像的体积缩减到一个真实的规格。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/7/building-container-images
|
||||
|
||||
作者:[Chris Collins][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[HankChow](https://github.com/HankChow)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/clcollins
|
||||
[1]:https://www.docker.com/
|
||||
[2]:https://www.nginx.com/
|
||||
[3]:https://rubyonrails.org/
|
||||
[4]:https://github.com/rbenv/rbenv
|
||||
[5]:https://opensource.com/article/18/6/getting-started-buildah
|
||||
[6]:https://twitter.com/TSweeneyRedHat
|
||||
[7]:https://opensource.com/article/18/5/containers-buildah
|
||||
[8]:https://www.gnu.org/software/coreutils/coreutils.html
|
||||
[9]:https://en.wikipedia.org/wiki/Static_library
|
||||
[10]:https://golang.org/
|
||||
[11]:https://twitter.com/kelseyhightower
|
||||
[12]:https://medium.com/@kelseyhightower/optimizing-docker-images-for-static-binaries-b5696e26eb07
|
||||
|
@ -1,5 +1,5 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: translator: (qhwdw)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
@ -7,24 +7,24 @@
|
||||
[#]: via: (https://opensource.com/article/19/3/raspberry-pi-entertainment)
|
||||
[#]: author: (Anderson Silva https://opensource.com/users/ansilva)
|
||||
|
||||
How to use your Raspberry Pi for entertainment
|
||||
如何用树莓派来娱乐
|
||||
======
|
||||
Learn how to watch Netflix and listen to music on your Raspberry Pi, in the eighth article in our guide to getting started with Raspberry Pi.
|
||||
在我们的树莓派使用入门的第八篇文章中,我们将学习如何使用树莓派观看 Netflix 上的影片和用它来听音乐。
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/video_editing_folder_music_wave_play.png?itok=-J9rs-My)
|
||||
|
||||
So far, this series has focused on more serious topics—how to [choose][1], [buy][2], [set up][3], and [update][4] your Raspberry Pi, and different things [kids][5] and [adults][6] can learn with it (including [Linux][7]). But now it's time to change up the subject and have some fun! Today we'll look at ways to use your Raspberry Pi for entertainment, and tomorrow we'll continue the fun with gaming.
|
||||
到目前为止,本系列文章已经学习了很多话题 — 如何 [挑选][1]、[购买][2]、[设置][3]、和 [更新][4] 你的树莓派,以及 [儿童][5] 和 [成人][6] 如何使用它来做的不同的事情(包括学习 [Linux][7])。今天我们换一个话题,将学习一些娱乐方面的内容!我们将学习如何使用树莓派来做一些娱乐方面的事情,明天我们继续这个话题,将用它来玩游戏。
|
||||
|
||||
### Watch TV and movies
|
||||
### 观看电视和电影
|
||||
|
||||
You can use your Raspberry Pi and the [Open Source Media Center][8] (OSMC) to [watch Netflix][9]! The OSMC is a system based on the [Kodi][10] project that allows you to play back media from your local network, attached storage, and the internet. It's also known for having the best feature set and community among media center applications.
|
||||
你可以使用你的树莓派和 [开源媒体中心][8] (OSMC) 去 [观看 Netflix][9]!OSMC 是一个基于 [Kodi][10] 项目的系统,你可以使用它来播放来自本地网络、附加存储、以及互联网上的多媒体。它因为良好的功能特性而在媒体播放应用界中拥有非常好的口碑。
|
||||
|
||||
NOOBS (which we talked about in the [third article][11] in this series) allows you to [install OSMC][12] on your Raspberry Pi as easily as possible. NOOBS also offers another media center system based on Kodi called [LibreELEC][13].
|
||||
NOOBS(我们在本系列的 [第三篇文章][11] 中介绍过它)可以让你在你的树莓派中很容易地 [安装 OSMC][12]。在 NOOBS 中也提供了另外一个基于 Kodi 项目的媒体播放系统,它的名字叫 [LibreELEC][13]。
|
||||
|
||||
### Listen to music
|
||||
### 听音乐
|
||||
|
||||
![](https://opensource.com/sites/default/files/uploads/raspberrypi_8_pimusicbox.png)
|
||||
|
||||
You can also stream music on your network via attached storage or services like Spotify on your Raspberry Pi with the [Pi Music Box][14] project. I [wrote about it][15] a while ago, but you can find newer instructions, including how to's and DIY projects, on the [Pi Music Box website][16].
|
||||
你还可以让你的树莓派借助 [Pi Music Box][14] 项目通过网络来播放来自附加存储或像 Spotify 服务上的流媒体音乐。以前我 [写过关于这个主题的文章][15],但是你可以在 [Pi Music Box 网站][16] 上找到最新的指导,包括如何使用和 DIY 项目。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -32,7 +32,7 @@ via: https://opensource.com/article/19/3/raspberry-pi-entertainment
|
||||
|
||||
作者:[Anderson Silva][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
译者:[qhwdw](https://github.com/qhwdw)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
@ -0,0 +1,48 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (qhwdw)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Let's get physical: How to use GPIO pins on the Raspberry Pi)
|
||||
[#]: via: (https://opensource.com/article/19/3/gpio-pins-raspberry-pi)
|
||||
[#]: author: (Anderson Silva https://opensource.com/users/ansilva)
|
||||
|
||||
进入物理世界:如何使用树莓派的 GPIO 针脚
|
||||
======
|
||||
在树莓派使用入门的第十篇文章中,我们将学习如何使用 GPIO。
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/raspbery_pi_zero_wireless_hardware.jpg?itok=9YFzdxFQ)
|
||||
|
||||
到目前为止,本系列文章主要专注于树莓派的软件方面,而今天我们将学习硬件。在树莓派最初发布时,最让我感兴趣的主要特性之一就是它的 [通用输入输出][1](GPIO)针脚。GPIO 可以让你的树莓派程序与连接到它上面的传感器、继电器、和其它类型的电子元件与物理世界来交互。
|
||||
|
||||
![](https://opensource.com/sites/default/files/uploads/raspberrypi_10_gpio-pins-pi2.jpg)
|
||||
|
||||
树莓派上的每个 GPIO 针脚要么有一个预定义的功能,要么被设计为通用的。另外,不同的树莓派型号要么 26 个,要么有 40 个 GPIO 针脚是你可以随意使用的。在维基百科上有一个 [关于每个针脚的非常详细的说明][2] 以及它的功能介绍。
|
||||
|
||||
你可以使用树莓派的 GPIO 针脚做更多的事情。关于它的 GPIO 的使用我写过一些文章,包括使用树莓派来控制节日彩灯的三篇文章([第一篇][3]、 [第二篇][4]、和 [第三篇][5]),在这些文章中我通过使用开源程序让灯光随着音乐起舞。
|
||||
|
||||
树莓派社区在不同编程语言上创建不同的库方面做了非常好的一些工作,因此,你能够使用 [C][6]、[Python][7]、 [Scratch][8]、和其它语言与 GPIO 进行交互。
|
||||
|
||||
另外,如果你想在树莓派与物理世界交互方面获得更好的体验,你可以选用 [Raspberry Pi Sense Hat][9],它是插入树莓派 GPIO 针脚上的一个很便宜的电路板,借助它你可以通过程序与 LED、驾驶杆、气压计、温度计、温度计、 陀螺仪、加速度计、以及磁力仪来交互。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/3/gpio-pins-raspberry-pi
|
||||
|
||||
作者:[Anderson Silva][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[qhwdw](https://github.com/qhwdw)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/ansilva
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.raspberrypi.org/documentation/usage/gpio/
|
||||
[2]: https://en.wikipedia.org/wiki/Raspberry_Pi#General_purpose_input-output_(GPIO)_connector
|
||||
[3]: https://opensource.com/life/15/2/music-light-show-with-raspberry-pi
|
||||
[4]: https://opensource.com/life/15/12/ssh-your-christmas-tree-raspberry-pi
|
||||
[5]: https://opensource.com/article/18/12/lightshowpi-raspberry-pi
|
||||
[6]: https://www.bigmessowires.com/2018/05/26/raspberry-pi-gpio-programming-in-c/
|
||||
[7]: https://www.raspberrypi.org/documentation/usage/gpio/python/README.md
|
||||
[8]: https://www.raspberrypi.org/documentation/usage/gpio/scratch2/README.md
|
||||
[9]: https://opensource.com/life/16/4/experimenting-raspberry-pi-sense-hat
|
@ -0,0 +1,62 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (hopefully2333)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Learn about computer security with the Raspberry Pi and Kali Linux)
|
||||
[#]: via: (https://opensource.com/article/19/3/computer-security-raspberry-pi)
|
||||
[#]: author: (Anderson Silva https://opensource.com/users/ansilva)
|
||||
|
||||
通过树莓派和 kali Linux 学习计算机安全
|
||||
======
|
||||
树莓派是学习计算机安全的一个好方法。在我们入门系列的第 11 篇文章中会进行学习。
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/security_privacy_lock.png?itok=ZWjrpFzx)
|
||||
|
||||
是否有比保护你的计算机更热门的技术?一些专家会告诉你,没有绝对安全的系统。他们开玩笑说,如果你想要你的服务器或者应用程序真正的安全,就关掉你的服务器,从网络上断线,然后把它放在一个安全的地方。但问题是显而易见的:没人能用的应用程序或者服务器有什么用?
|
||||
|
||||
这是围绕安全的一个难题,我们如何才能在保证安全性的同时,让服务器或应用程序依然可用且有价值?我无论如何都不是一个安全专家,虽然我希望有一天我能是。考虑到这一点,对于你能用树莓派做什么,分享和这有关的想法来学习计算机安全,我认为是有意义的。
|
||||
|
||||
我会注意到,就像本系列中其他写给树莓派初学者的文章一样,我的目标不是深入研究,而是起个头,让你有兴趣去了解更多与这些主题相关的东西。
|
||||
|
||||
### Kali Linux
|
||||
|
||||
当我们谈到“做一些安全方面的事”的时候,出现在脑海中的一个 Linux 发行版就是 Kali Linux。kali Linux 的开发主要集中在调查取证和渗透测试方面。它有超过 600 个已经预先安装好了的渗透测试工具来测试你的计算机的安全性,以及取证模式,它可以防止自己接触到内部的硬盘驱动器或是被检查系统的交换空间。
|
||||
|
||||
![](https://opensource.com/sites/default/files/uploads/raspberrypi_11_kali.png)
|
||||
|
||||
就像 Raspbian 一样,Kali Linux 基于 Debian 的发行版,你可以在 kali 的主文档门户网页上找到将它安装在树莓派上的文档(译者注:截至到翻译时,该网页是这个:https://docs.kali.org/kali-on-arm/install-kali-linux-arm-raspberry-pi)。如果你已经在你的树莓派上安装了 Raspbian 或者是其他的 Linux 发行版。那么你装 Kali 应该是没问题的,Kali 的创造者甚至将培训、研讨会和职业认证整合到了一起,以此来帮助提升你在安全领域内的职业生涯。
|
||||
|
||||
### 其他的 Linux 发行版
|
||||
|
||||
大多数的标准 Linux 发行版,比如 Raspbian,Ubuntu 和 Fedora 这些,在它们的仓库里同样也有很多可用的安全工具。一些很棒的探测工具包括 Nmap,Wireshark,auditctl,和 SELinux。
|
||||
|
||||
### 项目
|
||||
|
||||
你可以在树莓派上运行很多其他的安全相关的项目,例如蜜罐,广告拦截器和 USB 清洁器。花些时间了解它们!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/3/computer-security-raspberry-pi
|
||||
|
||||
作者:[Anderson Silva][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[hopefully2333](https://github.com/hopefully2333)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/ansilva
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.kali.org/
|
||||
[2]: https://en.wikipedia.org/wiki/Kali_Linux#Development
|
||||
[3]: https://docs.kali.org/general-use/kali-linux-forensics-mode
|
||||
[4]: https://docs.kali.org/kali-on-arm/install-kali-linux-arm-raspberry-pi
|
||||
[5]: https://www.kali.org/penetration-testing-with-kali-linux/
|
||||
[6]: https://linuxblog.darkduck.com/2019/02/9-best-linux-based-security-tools.html
|
||||
[7]: https://nmap.org/
|
||||
[8]: https://www.wireshark.org/
|
||||
[9]: https://linux.die.net/man/8/auditctl
|
||||
[10]: https://opensource.com/article/18/7/sysadmin-guide-selinux
|
||||
[11]: https://trustfoundry.net/honeypi-easy-honeypot-raspberry-pi/
|
||||
[12]: https://pi-hole.net/
|
||||
[13]: https://www.circl.lu/projects/CIRCLean/
|
Loading…
Reference in New Issue
Block a user