<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Yoshi Yamaguchi</title>
    <description>The latest articles on Forem by Yoshi Yamaguchi (@ymotongpoo).</description>
    <link>https://forem.com/ymotongpoo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F41338%2F7bdd9396-78d8-4811-90cd-a0d9e0967738.jpg</url>
      <title>Forem: Yoshi Yamaguchi</title>
      <link>https://forem.com/ymotongpoo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ymotongpoo"/>
    <language>en</language>
    <item>
      <title>What're inside OpenTelemetry Collector and ADOT?</title>
      <dc:creator>Yoshi Yamaguchi</dc:creator>
      <pubDate>Mon, 03 Mar 2025 09:31:18 +0000</pubDate>
      <link>https://forem.com/aws/whatre-inside-opentelemetry-collector-and-adot-152e</link>
      <guid>https://forem.com/aws/whatre-inside-opentelemetry-collector-and-adot-152e</guid>
      <description>&lt;p&gt;AWS has some observability services including Amazon CloudWatch, Amazon X-Ray, Amazon OpenSearch Service, and Amazon Managed Service for Prometheus. AWS Distro for OpenTelemetry (ADOT) is an option for sending telemetry data from applications you implement yourself to these services.&lt;/p&gt;

&lt;p&gt;In addition to a general description of the OpenTelemetry Collector, this article describes ADOT in detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;ADOT is a distribution of OpenTelemetry Collector for AWS that comes with the components you need to use the AWS and its partner solutions. If you want to use OpenTelemetry Collector in a more elaborate way, custom build is recommended.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is OpenTelemetry?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F99qny259j8ggn3eywg9v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F99qny259j8ggn3eywg9v.png" alt=" " width="661" height="309"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Though I know that many AWS users are already using OpenTelemetry, just in case let me briefly explain OpenTelemetry, a project under CNCF. OpenTelemetry is a project under CNCF that standardizes the instrumentation, collection and export of telemetry signals from the system.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is OpenTelemetry Collector?
&lt;/h2&gt;

&lt;p&gt;The OpenTelemetry Collector (hereafter "Collector") is an agent for instrumenting, collecting, and exporting telemetry that is being specified and a reference implementation is being developed by the OpenTelemetry project. The reference implementation runs as a single binary and is written in Go.&lt;/p&gt;

&lt;p&gt;It consists of three main components: receiver, processor, and exporter, and the required components are specified and made into a single binary before distribution.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Receiver: Responsible for receiving telemetry&lt;/li&gt;
&lt;li&gt;Processor: Responsible for processing and buffering of telemetry&lt;/li&gt;
&lt;li&gt;Exporter: Responsible for transmitting telemetry to the backend&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxlqt0v5j2pivvxmiacbb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxlqt0v5j2pivvxmiacbb.png" alt="OpenTelemetry Collector components" width="678" height="271"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The components included in the binary can be freely linked in the configuration file, but only in the direction of receiver, processor, and exporter &lt;sup id="fnref1"&gt;1&lt;/sup&gt;. Receivers and exporters can only be linked one at a time within a pipeline, while processors can be linked in multiple times.&lt;/p&gt;

&lt;p&gt;For example, the following configuration file shows receiving telemetry at OTLP, adjusting the flow rate of telemetry to be sent using the &lt;code&gt;batch&lt;/code&gt; and &lt;code&gt;memory_limiter&lt;/code&gt; processors, and then sending telemetry again at OTLP.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;receivers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;otlp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;processors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;batch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;memory_limiter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;limit_mib&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1536&lt;/span&gt;
    &lt;span class="na"&gt;spike_limit_mib&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;512&lt;/span&gt;
    &lt;span class="na"&gt;check_interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5s&lt;/span&gt;

&lt;span class="na"&gt;exporters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;otlp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pipelines&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metrics&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;receivers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;otlp&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;processors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;memory_limiter&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;batch&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;exporters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;otlp&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Collector's source code is available in GitHub repositories &lt;a href="https://github.com/open-telemetry/opentelemetry-collector/" rel="noopener noreferrer"&gt;&lt;code&gt;open-telemetry/opentelemetry-collector&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://github.com/open-telemetry/opentelemetry-collector-contrib/" rel="noopener noreferrer"&gt;&lt;code&gt;open-telemetry/opentelemetry-collector-contrib&lt;/code&gt;&lt;/a&gt; in which the source code of each component are available. In addition, they distribute several pre-built binaries of the collectors as &lt;a href="https://github.com/open-telemetry/opentelemetry-collector-releases/releases" rel="noopener noreferrer"&gt;the official OpenTelemetry project versions&lt;/a&gt;, as well as &lt;a href="https://hub.docker.com/u/otel" rel="noopener noreferrer"&gt;the OCI container that ships with them&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As of February 2025, four different builds are available for the officially distributed collectors, depending on the type of components included &lt;sup id="fnref2"&gt;2&lt;/sup&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;otelcol-otlp&lt;/code&gt;: Binary that can only receive and send OTLP. The file size is very small but has almost no functionality.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;otelcol&lt;/code&gt;: Binaries that support OSS that should be supported by OpenTelemetry project.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;otelcol-k8s&lt;/code&gt;: Binary with additional components for Kubernetes in addition to &lt;code&gt;otelcol&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;otelcol-contrib&lt;/code&gt;: This is a binary that includes all components managed under the OpenTelemetry project. The file size is very large, although all components, including those for Observability SaaS, can be used.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is ADOT (AWS Distro for OpenTelemetry)?
&lt;/h2&gt;

&lt;p&gt;If you want to use AWS components, the only way to achieve this with officially distributed collectors is to use &lt;code&gt;otelcol-contrib&lt;/code&gt;. However, this would be a waste of a large binary because it includes a large number of unnecessary components. Therefore, AWS provides a Collector distribution called &lt;a href="https://aws.amazon.com/jp/otel/" rel="noopener noreferrer"&gt;ADOT&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;ADOT pre-builds and &lt;a href="https://github.com/aws-observability/aws-otel-collector/releases" rel="noopener noreferrer"&gt;distributes&lt;/a&gt; the components used in the official otelcol distribution &lt;sup id="fnref3"&gt;3&lt;/sup&gt;, plus additional components that are useful for using AWS services and partner SaaS solutions. The binaries distributed here can be invoked by Amazon ECS, AWS Lambda, etc.&lt;/p&gt;

&lt;p&gt;For basic use of OpenTelemetry on AWS, using ADOT would be the first option.&lt;/p&gt;

&lt;h2&gt;
  
  
  Collector custom build
&lt;/h2&gt;

&lt;p&gt;On AWS, it is better to use ADOT Collector, but there will be components in ADOT that you will not use, and if you want to use OpenTelemetry in a more advanced way, you may not want to use these unnecessary components, or conversely, you may want to use components not included in ADOT. For example, the &lt;a href="https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/connector/spanmetricsconnector/README.md" rel="noopener noreferrer"&gt;Span Metrics Connector&lt;/a&gt; component, which converts distributed trace spans into metrics, is not included in ADOT. For such advanced use cases, the &lt;a href="https://github.com/open-telemetry/opentelemetry-collector/tree/main/cmd/builder" rel="noopener noreferrer"&gt;OpenTelemetry Collector builder (ocb)&lt;/a&gt; can be used.&lt;/p&gt;

&lt;p&gt;ocb is a convenient tool that allows you to build a Collector binary from the configuration in YAML file that lists the components you need in the form of Go package names. For example, to build a collector with only the following components, you need to create the following YAML file otelcol-foo.yaml&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/open-telemetry/opentelemetry-collector/tree/main/receiver/otlpreceiver" rel="noopener noreferrer"&gt;OTLP receiver&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/open-telemetry/opentelemetry-collector/tree/main/processor/batchprocessor" rel="noopener noreferrer"&gt;Batch processor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/open-telemetry/opentelemetry-collector/tree/main/processor/memorylimiterprocessor" rel="noopener noreferrer"&gt;Memory Limit processor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter/awsemfexporter" rel="noopener noreferrer"&gt;AWS CloudWatch EMF exporter&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dist&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;otelcol-foo&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Custom OpenTelemery Collector for Project foo AWS account&lt;/span&gt;
  &lt;span class="na"&gt;output_path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./otelcol-foo&lt;/span&gt;

&lt;span class="na"&gt;receivers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;gomod&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;go.opentelemetry.io/collector/receiver/otlpreceiver v0.119.0&lt;/span&gt;

&lt;span class="na"&gt;processors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;gomod&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;go.opentelemetry.io/collector/processor/batchprocessor v0.119.0&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;gomod&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.119.0&lt;/span&gt;

&lt;span class="na"&gt;exporters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;gomod&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.com/open-telemetry/opentelemetry-collector-contrib/exporter/awsemfexporter v0.119.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using this YAML file, a custom-built Collector is built by executing the ocb command as follows&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./ocb &lt;span class="nt"&gt;--config&lt;/span&gt; otelcol-foo.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I hope this article has deepened your understanding of the contents of ADOT, which has evolved along with the development of OpenTelemetry. In fact, the contents of ADOT have changed a little with each version. However, ADOT is only a custom build, so there is nothing to fear if you know what it is. We hope you will find it useful in selecting the best collector for your project.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;In the advanced use cases, the components called "Connector" is used, which loop backs the telemetry from the exporter to the receive. Because this artile aims at explaining basic concept of Collector, I omit the explanation of that part. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;Manifest files for each binary build can be found in the &lt;a href="https://github.com/open-telemetry/opentelemetry-collector-releases" rel="noopener noreferrer"&gt;&lt;code&gt;open-telemetry/opentelemetry-collector-releases&lt;/code&gt;&lt;/a&gt; repository. (&lt;a href="https://github.com/open-telemetry/opentelemetry-collector-releases/blob/main/distributions/otelcol-otlp/manifest.yaml" rel="noopener noreferrer"&gt;&lt;code&gt;otelcol-otlp&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://github.com/open-telemetry/opentelemetry-collector-releases/blob/main/distributions/otelcol/manifest.yaml" rel="noopener noreferrer"&gt;&lt;code&gt;otelcol&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://github.com/open-telemetry/opentelemetry-collector-releases/blob/main/distributions/otelcol-k8s/manifest.yaml" rel="noopener noreferrer"&gt;&lt;code&gt;otelcol-k8s&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://github.com/open-telemetry/opentelemetry-collector-releases/blob/main/distributions/otelcol-contrib/manifest.yaml" rel="noopener noreferrer"&gt;&lt;code&gt;otelcol-contrib&lt;/code&gt;&lt;/a&gt;) ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;The list of components included in ADOT can be found in the repository &lt;a href="https://github.com/aws-observability/aws-otel-collector?tab=readme-ov-file#adot-collector-built-in-components" rel="noopener noreferrer"&gt;README&lt;/a&gt;. The actual components can be found in &lt;a href="https://github.com/aws-observability/aws-otel-collector/blob/main/pkg/defaultcomponents/defaults.go" rel="noopener noreferrer"&gt;the Go source code&lt;/a&gt;. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>aws</category>
      <category>opentelemetry</category>
      <category>adot</category>
    </item>
    <item>
      <title>Revisit base container image for AWS services</title>
      <dc:creator>Yoshi Yamaguchi</dc:creator>
      <pubDate>Mon, 03 Feb 2025 07:51:58 +0000</pubDate>
      <link>https://forem.com/aws/revisit-base-container-image-for-aws-services-46k6</link>
      <guid>https://forem.com/aws/revisit-base-container-image-for-aws-services-46k6</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ue764ltkmjulydb1vvc.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ue764ltkmjulydb1vvc.jpeg" alt="Small containers" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hi, I'm Yoshi (&lt;a class="mentioned-user" href="https://dev.to/ymotongpoo"&gt;@ymotongpoo&lt;/a&gt;). Are you enjoying building your container images for serverless and container runtime solutions in AWS? Many container runtime services exist in AWS, including Amazon ECS, Amazon EKS and AWS Lambda. The first step in using such container runtimes is to create a container image. AWS provides &lt;a href="https://gallery.ecr.aws/amazonlinux/amazonlinux" rel="noopener noreferrer"&gt;&lt;code&gt;amazonlinux&lt;/code&gt;&lt;/a&gt; images, and they are about 50 MB by default. Some people may be trying to reduce the size of the image in order to launch the container image as quickly as possible.&lt;/p&gt;

&lt;p&gt;There are already many practices to reduce container size, but in this article, I would like to focus on the base image and discuss the characteristics of each. This article assumes that images are built based on Dockerfile. Unless otherwise noted below, image sizes are for the &lt;code&gt;latest&lt;/code&gt; tag for arm64 as of January 9, 2025.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;I introduced scratch, busybox, alpine, Debian slim, UBI, Distroless, and Chainguard Image as base images for minimizing container size.&lt;/p&gt;

&lt;h2&gt;
  
  
  scratch
&lt;/h2&gt;

&lt;p&gt;The most primitive way to create a minimal container image is to use an official Docker image called &lt;a href="https://hub.docker.com/_/scratch" rel="noopener noreferrer"&gt;&lt;code&gt;scratch&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This scratch image is used in the bottom layer of many container images. For example, the &lt;a href="https://registry.hub.docker.com/_/hello-world/" rel="noopener noreferrer"&gt;&lt;code&gt;hello-world&lt;/code&gt;&lt;/a&gt; image that they usualy use to check if Docker is working properly is created with the following Dockerfile (where &lt;code&gt;hello&lt;/code&gt; is the executable binary included in the repository where the image is created.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; scratch&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; hello /&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["/hello"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;scratch&lt;/code&gt;, to put it bluntly, only contains nothing and is only available to talk to the kernel of the host OS, so you need to provide all the other necessary files by yourself. In exchange for the freedom to add the files you only need, you have to copy files at a very primitive level (there is no package manager, of course). If you want to create an application environment, you will need to copy a lot of files, including dependent libraries, and it will be difficult to put everything in a Dockerfile. In many cases, you will need to use a container image that ships with some common dependency libraries.&lt;/p&gt;

&lt;h2&gt;
  
  
  busybox
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://hub.docker.com/_/busybox" rel="noopener noreferrer"&gt;&lt;code&gt;busybox&lt;/code&gt;&lt;/a&gt; container is, as the name suggests, a base image that contains the minimum environment for &lt;a href="https://busybox.net/" rel="noopener noreferrer"&gt;BusyBox&lt;/a&gt; to work. It is also one of the official Docker images. The actual Dockerfile for creating this image is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; scratch&lt;/span&gt;
&lt;span class="k"&gt;ADD&lt;/span&gt;&lt;span class="s"&gt; busybox.tar.gz /&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["sh"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see that &lt;a href="https://busybox.net/downloads/" rel="noopener noreferrer"&gt;&lt;code&gt;busybox.tar.gz&lt;/code&gt;&lt;/a&gt;&lt;sup id="fnref1"&gt;1&lt;/sup&gt; is simply extracted on top of the scratch image we introduced earlier.&lt;/p&gt;

&lt;p&gt;Although &lt;code&gt;busybox&lt;/code&gt; uses ash, it can use shells, is small (1.76MB), and has a choice of standard C libraries (libc): glibc and musl &lt;sup id="fnref2"&gt;2&lt;/sup&gt;. This image is an option if you just want to run a simple shell script or a binary that runs by itself.&lt;/p&gt;

&lt;p&gt;However, there is no package manager, so if you want to install libraries and so on, you have to copy them in the same way as &lt;code&gt;scratch&lt;/code&gt;. You may need to do a lot of work to write a Dockerfile-based description.&lt;/p&gt;

&lt;h2&gt;
  
  
  alpine
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://hub.docker.com/_/alpine" rel="noopener noreferrer"&gt;&lt;code&gt;alpine&lt;/code&gt;&lt;/a&gt; is a base image using a very lightweight Linux distribution called &lt;a href="https://alpinelinux.org/" rel="noopener noreferrer"&gt;Alpine Linux&lt;/a&gt;, which includes BusyBox and musl environments, as well as a package management tool called &lt;a href="https://wiki.alpinelinux.org/wiki/Alpine_Package_Keeper" rel="noopener noreferrer"&gt;APK (Alpine Package Manager)&lt;/a&gt;. The image size is 3.81MB, which is very lightweight. Many of you are probably using alpine as a base image to create container images.&lt;/p&gt;

&lt;p&gt;Although &lt;code&gt;alpine&lt;/code&gt; is lightweight and the APK makes it easy to create an environment, its use of musl in the libc makes it inconvenient in many situations. For example, there are the following inconveniences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does not support extensions provided by glibc&lt;/li&gt;
&lt;li&gt;There are thread-ussafe cases when running on musl&lt;/li&gt;
&lt;li&gt;Difficulty in handling shared libraries (musl can't do lazy binding and can't unload)&lt;/li&gt;
&lt;li&gt;Small thread stack size, easy to encounter segmentation violations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have had experienced cases where Python and other programs didn't work well with alpine.&lt;/p&gt;

&lt;p&gt;Because of these troubles, it is my understanding that the preferences of the base image is now diverse as follows, assuming to use glibc for libc:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;a slightly larger image that includes a shell and package manager and can be easily described in a Dockerfile&lt;/li&gt;
&lt;li&gt;a very small image with only the necessary configuration for each individual use&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Debian slim
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://hub.docker.com/_/debian/tags?name=slim" rel="noopener noreferrer"&gt;&lt;code&gt;debian:xxx-slim&lt;/code&gt;&lt;/a&gt; is part of Debian's official Docker images and, as the name suggests, is a Debian-based image with a small image size. The shell is bash by default, and you can freely install stable packages released by Debian via &lt;code&gt;apt&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;With an image size of 26.76 MB (&lt;code&gt;stable-slim&lt;/code&gt;), it is much larger than other minimum images, but considering that the runtimes of various languages themselves are tens to hundreds of MB, the image size would be affordable as an application image.&lt;/p&gt;

&lt;p&gt;Debian slim images are used as the slim base image for official images of many languages due to its stability. (Footnote: Example on Python 3.13.1)&lt;/p&gt;

&lt;h2&gt;
  
  
  Red Hat Universal Base Image
&lt;/h2&gt;

&lt;p&gt;While most of the official images released by the OSS project are Debian based, there is also demand for images from RHEL-based distributions. For this purpose, Red Hat offers an image called Universal Base Image (UBI).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://hub.docker.com/r/redhat/ubi9-micro" rel="noopener noreferrer"&gt;&lt;code&gt;redhat/ubi9-micro&lt;/code&gt;&lt;/a&gt;: Minimal environment with almost nothing but bash and glibc, 6.33MB, similar to busybox.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hub.docker.com/r/redhat/ubi9-minimal/" rel="noopener noreferrer"&gt;&lt;code&gt;redhat/ubi9-minimal&lt;/code&gt;&lt;/a&gt;: Same purpose as Debian slim, but with microdnf. 35.84MB.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are two other image types, Standard and Init, but I don't detail them here because they are out of the scope of the main purpose of the minimum image.&lt;/p&gt;

&lt;h2&gt;
  
  
  Distroless
&lt;/h2&gt;

&lt;p&gt;Debian slim and UBI are easy to use in the direction of creating a very small image while taking into account the use of a package manager, but on the other hand, they are too large to satisfy the demand to create a minimum image for a specific language environment. If you want to satisfy such a demand, &lt;a href="https://github.com/GoogleContainerTools/distroless" rel="noopener noreferrer"&gt;Distroless image&lt;/a&gt; may be the right choice for you.&lt;/p&gt;

&lt;p&gt;As of January 2025, the latest version of Distroless is based on Debian 12.4. This does not mean that it is based on Debian slim, but rather that it only extracts the deb files from the Debian repositories for the packages needed for &lt;code&gt;scratch&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The image will vary depending on the package it is in, but these are the two basic ones.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;gcr.io/distroless/static-debian12&lt;/code&gt; (less than 800KB): contains &lt;code&gt;ca-certificate&lt;/code&gt; files, &lt;code&gt;base-files&lt;/code&gt;, &lt;code&gt;tzdata&lt;/code&gt; and other minimal packages&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gcr.io/distroless/base-debian12&lt;/code&gt; (8.5MB): contains &lt;code&gt;glibc&lt;/code&gt; and &lt;code&gt;libssl&lt;/code&gt; in addition to &lt;code&gt;static-debian12&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, you can create a very small image on top of &lt;code&gt;static-debian12&lt;/code&gt; with a Go executable binary that can run as a single binary without depending on libc. There are also images based on these two images for commonly used languages, such as the followings for Java and Python.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;gcr.io/distroless/java17-debian12&lt;/code&gt; (88MB): contains &lt;code&gt;base-debian12&lt;/code&gt; plus OpenJDK 17 and its dependencies distributed by Debian&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gcr.io/distroless/java21-debian12&lt;/code&gt; (68MB): contains &lt;a href="https://adoptium.net/temurin/archive/?version=21" rel="noopener noreferrer"&gt;Temurin OpenJDK 21&lt;/a&gt; and its dependencies in addition to &lt;code&gt;base-debian12&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gcr.io/distroless/python3-debian12&lt;/code&gt; (21MB): contains &lt;a href="https://packages.debian.org/bookworm/arm64/python3.11-minimal" rel="noopener noreferrer"&gt;&lt;code&gt;python3.11-minimal&lt;/code&gt;&lt;/a&gt; and its dependencies in addition to &lt;code&gt;base-debian12&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since these images do not include the shell, if you really want to use the shell during development, for example, there is a &lt;code&gt;debug&lt;/code&gt; image for each of these images. This can be done by specifying the tag &lt;code&gt;debug&lt;/code&gt; (e.g. &lt;code&gt;gcr.io/distroless/base-debian12:debug&lt;/code&gt;) for the above images, and you will get an image with &lt;code&gt;busybox&lt;/code&gt; installed in addition to the environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Chainguard Images
&lt;/h2&gt;

&lt;p&gt;As the name suggests, these are publicly available container images from &lt;a href="https://images.chainguard.dev/" rel="noopener noreferrer"&gt;Chainguard&lt;/a&gt;. Because Chainguard is a company specialising in container security and supply chain security, these container images have security measures in place in many ways, and the images they distribute advocate "low-to-no CVEs".&lt;/p&gt;

&lt;p&gt;Chainguard Images is greatly influenced by Distroless, which is introduced above, and while following the essence of Distroless, it has developed its own unique style. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OSS distribution for container image creation called &lt;a href="https://github.com/wolfi-dev/" rel="noopener noreferrer"&gt;Wolfi OS&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/chainguard-dev/apko" rel="noopener noreferrer"&gt;apko&lt;/a&gt;, an new OCI container image builder&lt;/li&gt;
&lt;li&gt;Developed our own apk package builder called &lt;a href="https://github.com/chainguard-dev/melange" rel="noopener noreferrer"&gt;melenge&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By taking full advantage of these, they are creating a minimum size container with only packages that are always provided by SBOM and instantly patched for security. The publicly available images they provide, for example, if you want something like &lt;code&gt;busybox&lt;/code&gt; or Distroless' &lt;code&gt;base&lt;/code&gt; image, are as follows&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cgr.dev/chainguard/glibc-dynamic&lt;/code&gt; (4.13MB)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cgr.dev/chainguard/busybox&lt;/code&gt; (3.59MB)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want a small base for additional packages like &lt;code&gt;alpine&lt;/code&gt;, or a minimum image for each language like Distroless, you can use the following images:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cgr.dev/chainguard/wolfi-base&lt;/code&gt; (5.40MB)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cgr.dev/chainguard/python&lt;/code&gt; (20.9MB)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cgr.dev/chainguard/jdk&lt;/code&gt; (104.1MB)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Chainguard Images are awesome, but one point to note is that only images classified as Developer Images are freely available. For example, the images listed above are only freely available under the &lt;code&gt;latest&lt;/code&gt; tag, and if you want to stick to a specific version, you need to use Chainguard's paid-for service.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, we introduced various base images for container image minimization. There is a wide range of configurations required to create container images when running applications, as many different conditions need to be taken into account. In addition to Docker, there are also other container creation tools such as Buildah, Buildpacks, Bazel, ko, kaniko, etc., that can be used for a variety of purposes. I hope this article will be helpful in determining the best base image for your development process and usage.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;The exact tarball is a modified version for each CPU platform. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;uClibc is also available, but it is not used by many. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>aws</category>
      <category>container</category>
      <category>docker</category>
    </item>
    <item>
      <title>Run remote install scripts without using `curl` command in Ansible</title>
      <dc:creator>Yoshi Yamaguchi</dc:creator>
      <pubDate>Thu, 04 Mar 2021 00:54:12 +0000</pubDate>
      <link>https://forem.com/ymotongpoo/run-remote-install-scripts-without-using-curl-command-in-ansible-5b6b</link>
      <guid>https://forem.com/ymotongpoo/run-remote-install-scripts-without-using-curl-command-in-ansible-5b6b</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;ansible.builtin.uri&lt;/code&gt; to fetch the script content, and pass it through &lt;code&gt;stdin&lt;/code&gt; parameter of &lt;code&gt;ansible.builtin.shell&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Execution environment
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ansible: 2.10.5&lt;/li&gt;
&lt;li&gt;Python: 3.8.7&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Sample case
&lt;/h2&gt;

&lt;p&gt;There are a lot of cases where the install instructions of tool X introduces the remote script to run. For instance, &lt;a href="https://rustup.rs/" rel="noopener noreferrer"&gt;rustup&lt;/a&gt; gives the script as the primary method to install it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--proto&lt;/span&gt; &lt;span class="s1"&gt;'=https'&lt;/span&gt; &lt;span class="nt"&gt;--tlsv1&lt;/span&gt;.2 &lt;span class="nt"&gt;-sSf&lt;/span&gt; https://sh.rustup.rs | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the case you install rustup via Ansible, you may want to write lines like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run rustup&lt;/span&gt;
  &lt;span class="na"&gt;ansible.builtin.shell&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;cmd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;curl -sSf https://sh.rustup.rs | sh -s -- -y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(I added &lt;code&gt;-s&lt;/code&gt; option to install the script without prompt that blocks the Ansible installation process.)&lt;/p&gt;

&lt;p&gt;Ansible warns when it runs the task like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TASK [common : Run rustup] **********************************************************************************
[WARNING]: Consider using the get_url or uri module rather than running 'curl'.  If you need to use command
because get_url or uri is insufficient you can add 'warn: false' to this command task or set
'command_warnings=False' in ansible.cfg to get rid of this message.
changed: [dev]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;The easiest way to avoid this is to use &lt;code&gt;get_url&lt;/code&gt; to download the shell script and run it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Download rustup&lt;/span&gt;
  &lt;span class="na"&gt;ansible.builtin.get_url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://sh.rustup.rs&lt;/span&gt;
    &lt;span class="na"&gt;dest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/tmp/rustup.sh&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run rustup&lt;/span&gt;
  &lt;span class="na"&gt;ansible.builtin.shell&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;cmd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cat /tmp/rustup.sh | sh -s -- -y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Otherwise, you can directly pass the script contents into stdin of &lt;code&gt;shell&lt;/code&gt; with &lt;code&gt;stdin&lt;/code&gt; parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Fetch rustup&lt;/span&gt;
  &lt;span class="na"&gt;ansible.builtin.uri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://sh.rustup.rs&lt;/span&gt;
    &lt;span class="na"&gt;return_content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
  &lt;span class="na"&gt;register&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rustup_installer&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run rustup installer&lt;/span&gt;
  &lt;span class="na"&gt;ansible.builtin.shell&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;cmd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sh -s -- -y&lt;/span&gt;
    &lt;span class="na"&gt;stdin&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;rustup_installer.content&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>ansible</category>
      <category>provisioning</category>
    </item>
    <item>
      <title>Automatically installing Cloud Operations agents with Policy Agent</title>
      <dc:creator>Yoshi Yamaguchi</dc:creator>
      <pubDate>Wed, 12 Aug 2020 06:25:53 +0000</pubDate>
      <link>https://forem.com/googlecloud/installing-cloud-operations-agents-with-policy-agent-5</link>
      <guid>https://forem.com/googlecloud/installing-cloud-operations-agents-with-policy-agent-5</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Agent Policy frees you from installing Google Cloud Logging and Google Cloud Monitoring agents to Google Compute Engine instances.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preface
&lt;/h2&gt;

&lt;p&gt;In Google Cloud Platform (GCP), &lt;a href="https://cloud.google.com/logging/docs" rel="noopener noreferrer"&gt;Google Cloud Logging&lt;/a&gt; and &lt;a href="https://cloud.google.com/monitoring/docs" rel="noopener noreferrer"&gt;Google Cloud Monitoring&lt;/a&gt; (hereinafter called Logging and Monitoring) are integrated with peer GCP services, and the users can observe system/audit logs and system metrics without any configurations. Also, application and container runtimes such as Google App Engine and Google Kubernetes Engine sends logs and metrics automatically to Logging and Monitoring.&lt;/p&gt;

&lt;p&gt;However, when you run applications directly on top of Google Compute Engine, you had to install and setup the agents for Google Cloud Logging and Google Cloud Monitoring respectively all by yourselves.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to setup Agent Policy
&lt;/h2&gt;

&lt;p&gt;The required steps are explained in &lt;a href="https://cloud.google.com/stackdriver/docs/solutions/managing-agent-policies" rel="noopener noreferrer"&gt;the official document&lt;/a&gt; and this post provides the additional demo to explain how it works.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install &lt;code&gt;gcloud alpha&lt;/code&gt; components
&lt;/h3&gt;

&lt;p&gt;Agent Policy is still in alpha, and you need to install the alpha components to try it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ gcloud components install alpha
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set up proper privileges
&lt;/h3&gt;

&lt;p&gt;GCP (and any other cloud platforms) always about IAMs. Setting up proper privileges and roles are important, or even mandatory to run specific features. Agent Policy is not the exception and you need to set up multiple IAM roles to multiple users and service accounts. However, the good news is the official supplemental shell script is provided.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/stackdriver/docs/set-permissions.sh" rel="noopener noreferrer"&gt;set-permissions.sh&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The details of what it does are well described in &lt;a href="https://cloud.google.com/stackdriver/docs/solutions/managing-agent-policies#set-permissions-script" rel="noopener noreferrer"&gt;the document&lt;/a&gt;. In short, it assigns &lt;code&gt;roles/osconfig&lt;/code&gt; to appropriate users and service accounts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create Agent Policy
&lt;/h3&gt;

&lt;p&gt;After setting up IAMs, now the main part. Create an Agent Policy with &lt;code&gt;gcloud&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;For example, this example create an Agent Policy named &lt;code&gt;ops-agents-debian&lt;/code&gt;: it installs Logging and Monitoring agents to new GCE instances generated from Debian 10 images. (See &lt;a href="https://cloud.google.com/compute/docs/images#list_of_public_images_available_on" rel="noopener noreferrer"&gt;the list of public images&lt;/a&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ gcloud alpha compute instances ops-agents policies create ops-agents-debian \
  --agent-rules="type=logging,version=current-major,package-state=installed,enable-autoupgrade=true;type=metrics,version=current-major,package-state=installed,enable-autoupgrade=true" \
  --os-types=short-name=debian,version=10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And all set! This example applies to all Debian 10 images. In the real use cases, you may want to set up more complex condition to apply Agent Policy, and using &lt;code&gt;--group-labels&lt;/code&gt; should be better idea. Please find the details of the options of &lt;a href="https://cloud.google.com/sdk/gcloud/reference/alpha/compute/instances/ops-agents/policies/create" rel="noopener noreferrer"&gt;&lt;code&gt;gcloud alpha compute instances ops-agents policies create&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Experiments
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Case 1: Create a new instance with Debian 10
&lt;/h3&gt;

&lt;p&gt;Let's see if the policy installs agents to Debian 10 instances. Run the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ gcloud compute instances create test0 \
  --image-project debian-cloud \
  --image-family=debian-10 \
  --zone=us-central1-a \
  --preemptible \
  --boot-disk-auto-delete
Created [https://www.googleapis.com/compute/v1/projects/agents-install-test/zones/us-central1-a/instances/test0].
NAME   ZONE           MACHINE_TYPE   PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP    STATUS
test0  us-central1-a  n1-standard-1  true         XX.XX.XX.XX   XX.XX.XX.XX  RUNNING
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And confirm if Logging and Monitoring agents are installed and running.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ gcloud compute ssh test0 --zone=us-central1-a
Writing 3 keys to /home/ymotongpoo/.ssh/google_compute_known_hosts
Enter passphrase for key '/home/ymotongpoo/.ssh/google_compute_engine':
Linux test0 4.19.0-10-cloud-amd64 #1 SMP Debian 4.19.132-1 (2020-07-24) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
ymotongpoo@test0:~$ sudo service google-fluentd status
● google-fluentd.service - LSB: data collector for Treasure Data
   Loaded: loaded (/etc/init.d/google-fluentd; generated)
   Active: active (running) since Tue 2020-08-11 08:50:36 UTC; 1min 17s ago
     Docs: man:systemd-sysv-generator(8)
    Tasks: 110 (limit: 4373)
   Memory: 66.9M
   CGroup: /system.slice/google-fluentd.service
           └─2128 /opt/google-fluentd/embedded/bin/ruby /usr/sbin/google-fluentd --log /var/log/google-fluentd/goo

Aug 11 08:50:36 test0 systemd[1]: Starting LSB: data collector for Treasure Data...
Aug 11 08:50:36 test0 google-fluentd[2106]: Starting google-fluentd 1.7.1: google-fluentd.
Aug 11 08:50:36 test0 systemd[1]: Started LSB: data collector for Treasure Data.
ymotongpoo@test0:~$ sudo service stackdriver-agent status
● stackdriver-agent.service - LSB: start and stop Stackdriver Agent
   Loaded: loaded (/etc/init.d/stackdriver-agent; generated)
   Active: active (running) since Tue 2020-08-11 08:50:42 UTC; 1min 32s ago
     Docs: man:systemd-sysv-generator(8)
    Tasks: 13 (limit: 4373)
   Memory: 6.2M
   CGroup: /system.slice/stackdriver-agent.service
           └─2470 /opt/stackdriver/collectd/sbin/stackdriver-collectd -C /etc/stackdriver/collectd.conf -P /var/ru

Aug 11 08:50:42 test0 collectd[2469]: plugin_load: plugin "write_gcm" successfully loaded.
Aug 11 08:50:42 test0 collectd[2469]: plugin_load: plugin "match_regex" successfully loaded.
Aug 11 08:50:42 test0 collectd[2469]: plugin_load: plugin "match_throttle_metadata_keys" successfully loaded.
Aug 11 08:50:42 test0 collectd[2469]: plugin_load: plugin "stackdriver_agent" successfully loaded.
Aug 11 08:50:42 test0 collectd[2469]: plugin_load: plugin "exec" successfully loaded.
Aug 11 08:50:42 test0 collectd[2469]: plugin_load: plugin "aggregation" successfully loaded.
Aug 11 08:50:42 test0 stackdriver-agent[2449]: .
Aug 11 08:50:42 test0 systemd[1]: Started LSB: start and stop Stackdriver Agent.
Aug 11 08:50:42 test0 collectd[2470]: Initialization complete, entering read-loop.
Aug 11 08:50:42 test0 collectd[2470]: tcpconns plugin: Reading from netlink succeeded. Will use the netlink method
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, they are running!&lt;/p&gt;

&lt;h3&gt;
  
  
  Case 2: Create a new instance with CentOS 8
&lt;/h3&gt;

&lt;p&gt;This time, I create an instance with CentOS 8, which doesn't apply to the &lt;code&gt;ops-agent-debian&lt;/code&gt; policy I made.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ gcloud compute instances create test1 \
  --image-project=centos-cloud \
  --image-family=centos-8 \
  --zone=us-central1-a \
  --preemptible \
  --boot-disk-auto-delete
Created [https://www.googleapis.com/compute/v1/projects/agents-install-test/zones/us-central1-a/instances/test0].
NAME   ZONE           MACHINE_TYPE   PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP     STATUS
test1  us-central1-a  n1-standard-1  true         XX.XX.XX.XX   XX.XX.XX.XX  RUNNING

$ gcloud compute ssh test1 --zone=us-central1-a                                                                  Writing 3 keys to /home/ymotongpoo/.ssh/google_compute_known_hosts
Enter passphrase for key '/home/ymotongpoo/.ssh/google_compute_engine':
[ymotongpoo@test0 ~]$ sudo service google-fluentd status
Redirecting to /bin/systemctl status google-fluentd.service
Unit google-fluentd.service could not be found.

[ymotongpoo@test0 ~]$ sudo service stackdriver-agent status
Redirecting to /bin/systemctl status stackdriver-agent.service
Unit stackdriver-agent.service could not be found.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This time, the agents are not installed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Notes
&lt;/h2&gt;

&lt;p&gt;As of Aug 12th, 2020, this feature is in alpha and only supported for the direct use of public images on GCE. (The supported short names are &lt;code&gt;centos&lt;/code&gt;, &lt;code&gt;debian&lt;/code&gt;, &lt;code&gt;rhel&lt;/code&gt;, &lt;code&gt;sles&lt;/code&gt;, &lt;code&gt;sles-sap&lt;/code&gt; and &lt;code&gt;ubuntu&lt;/code&gt;) This doesn't support containers running on GCE.&lt;/p&gt;

&lt;p&gt;Also, this only works on &lt;code&gt;gcloud&lt;/code&gt; command and is not available on Cloud Console and public APIs. In order to confirm existing policies and their details, you need to run the following commands respectively.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;gcloud alpha compute instances ops-agents list&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gcloud alpha compute instances ops-agents describe POLICY_ID&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because this is still in alpha, we appreciate your feedback. Please drop your experiences to &lt;a href="mailto:ops-agent-policy-feedback@google.com"&gt;ops-agent-policy-feedback@google.com&lt;/a&gt; or &lt;a href="https://twitter.com/ymotongpoo" rel="noopener noreferrer"&gt;@ymotongpoo&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>cloudmonitoring</category>
      <category>cloudlogging</category>
      <category>gce</category>
      <category>googlecloud</category>
    </item>
    <item>
      <title>Easter eggs in Go source code</title>
      <dc:creator>Yoshi Yamaguchi</dc:creator>
      <pubDate>Tue, 21 Jul 2020 01:14:40 +0000</pubDate>
      <link>https://forem.com/ymotongpoo/easter-eggs-in-go-source-code-2l02</link>
      <guid>https://forem.com/ymotongpoo/easter-eggs-in-go-source-code-2l02</guid>
      <description>&lt;h2&gt;
  
  
  Preface
&lt;/h2&gt;

&lt;p&gt;A week ago, I had a small chat with my friend over some Slack workspace, something like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;friend: "Does anyone know why &lt;code&gt;time.minWall&lt;/code&gt; defaults to 1885?"&lt;br&gt;
me: "No idea, maybe it's from the year in &lt;em&gt;Back To The Future 3&lt;/em&gt;?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At that time, I was almost joking but I had no idea why it was set to 1885 neither. Though the fact behind it does not have anything to do with my daily coding in Go, I couldn't help asking the behind-the-scene. I asked my peer Gophers in the team chat, but it seemed no one there couldn't reach the clues for the decision.&lt;/p&gt;

&lt;p&gt;Finally, I sent an email to Russ Cox (&lt;a href="https://twitter.com/_rsc" rel="noopener noreferrer"&gt;@_rsc&lt;/a&gt;) directly to know the background for the decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;time.minWall&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;A const value &lt;code&gt;time.minWall&lt;/code&gt; is set to 1885.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://go.googlesource.com/go/+/refs/tags/go1.14.5/src/time/time.go#153" rel="noopener noreferrer"&gt;src/time/time.go - go - Git at Google&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const (
    hasMonotonic = 1 &amp;lt;&amp;lt; 63
    maxWall      = wallToInternal + (1&amp;lt;&amp;lt;33 - 1) // year 2157
    minWall      = wallToInternal               // year 1885
    nsecMask     = 1&amp;lt;&amp;lt;30 - 1
    nsecShift    = 30
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the constant value that defines the epoch of values in time package. We often use UNIX epoch (i.e. 00:00:00 UTC on 1st January 1970), but it is just one epoch out of a couple of standards or implementations to express datetime values, and of course Go is a multi platform language, so the epoch in Go need to cover all those platforms.&lt;/p&gt;

&lt;p&gt;Russ Cox had given comments on Go's epoch publicly in the following places. The first one is on &lt;a href="https://github.com/golang/go/issues/12914#issuecomment-277335863" rel="noopener noreferrer"&gt;the GitHub issue thread&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;OK, this is checked in for Go 1.9. I moved the internal epoch to 1885 (max year 2157) to avoid any possible problem with NTP-epoch-derived times. I also adjusted the design doc to reflect this change and some minor encoding changes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But this comment only mentions why and when they moved the internal epoch to 1885, but not why they didn't to any other years, such as 1900.&lt;/p&gt;

&lt;p&gt;The second one is the proposal doc for the move of the internal epoch.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://go.googlesource.com/proposal/+/master/design/12914-monotonic.md" rel="noopener noreferrer"&gt;Proposal: Monotonic Elapsed Time Measurement in Go&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Unix-based systems often use 1970, and Windows-based systems often use 1980. We are unaware of any systems using earlier default wall times, but since the NTP protocol epoch uses 1900, it seemed more future-proof to choose a year before 1900.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Okay, still the rationale supports any years before 1900, not specifically 1885. I was almost sure that the year is derived from &lt;em&gt;Back To The Future 3&lt;/em&gt;, but I wanted 100% sure for it and I reached out to the person who only knows the decision behind it; I sent an email to Russ to ask the reason. He gave a response within a day (it's super quick, considering timezone difference between EDT and JST) saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Yes, people talked me into moving it back before 1900, and 1885 was the obvious choice due to its historical significance to Hill Valley, California. :-)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I knew it!! Also, it was more than happy that I could get the true answer from who made the decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;http.aLongTimeAgo&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;While I appreciated the answer from Russ, it was not the end of the story. There was the another line in Russ' reply.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;See also http.aLongTimeAgo, which is now sadly set to time.Unix(1, 0) but used to be time.Unix(233431200, 0).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In Go 1.14.5, as he says, it's set to &lt;code&gt;time.Unix(1, 0)&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://go.googlesource.com/go/+/refs/tags/go1.14.5/src/net/http/http.go#25" rel="noopener noreferrer"&gt;Go 1.14.5: src/net/http/http.go - go - Git at Google&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// aLongTimeAgo is a non-zero time, far in the past, used for
// immediate cancellation of network operations.
var aLongTimeAgo = time.Unix(1, 0)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So let's confirm its original value when it was introduced to the source code. You can find it in Go 1.8.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://go.googlesource.com/go/+/refs/tags/go1.8/src/net/http/http.go#23" rel="noopener noreferrer"&gt;Go 1.8: src/net/http/http.go - go - Git at Google&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// aLongTimeAgo is a non-zero time, far in the past, used for
// immediate cancelation of network operations.
var aLongTimeAgo = time.Unix(233431200, 0)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's convert the UNIX time to human readable format. Of course, Go gives super easy way to do it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://play.golang.org/p/c4u1lF5Q6xQ" rel="noopener noreferrer"&gt;Sample code to read UNIX time in human readable format&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "fmt"
    "time"
)

func main() {
    pdt, _ := time.LoadLocation("America/Los_Angeles")
    t := time.Unix(233431200, 0).In(pdt)
    fmt.Println(t)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1977-05-25 11:00:00 -0700 PDT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We got 2 hints: "A Long Time Ago" and "May 25th, 1977". What these 2 lead to is...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhht1vvzyqi1ybuyucn2j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhht1vvzyqi1ybuyucn2j.png" alt="A long time ago..." width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Of course, nothing but &lt;em&gt;Star Wars: Episode IV&lt;/em&gt;. It was released on May 25th, 1977 (&lt;a href="https://en.wikipedia.org/wiki/Star_Wars_(film)" rel="noopener noreferrer"&gt;Wikipedia&lt;/a&gt;) &lt;/p&gt;

&lt;p&gt;How this value is used in Go package is to force cancelling existing connections immediately by giving deadlines in past time, such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cr.conn.rwc.SetReadDeadline(aLongTimeAgo)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some people reacted on the changes when the value was changed to &lt;code&gt;time.Unix(1, 0)&lt;/code&gt;. I love to see these kinds of comments; those fun chats occasionally happen in changelists.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/golang/go/commit/6983b9a57955fa12ecd81ab8394ee09e64ef21b9" rel="noopener noreferrer"&gt;net, net/http: adjust time-in-past constant even earlier&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Acknowledgement
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Russ Cox: Thank you for replying to my question and the additional information. Also, thank you for the approval to share this publicly. Quoting his comment:&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Feel free. No secrets here.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/broady" rel="noopener noreferrer"&gt;Chris Broadfoot&lt;/a&gt; and &lt;a href="https://twitter.com/val_deleplace" rel="noopener noreferrer"&gt;Valentin Deleplace&lt;/a&gt;: Thank you for finding out the clues together on the group chat.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/mattn_jp" rel="noopener noreferrer"&gt;mattn&lt;/a&gt;: Thank you for letting me know the GitHub thread where people reacted on the value. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Note
&lt;/h2&gt;

&lt;p&gt;This entry was originally posted to my Japanese blog on July 17th.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ymotongpoo.hatenablog.com/entry/2020/07/17/093000" rel="noopener noreferrer"&gt;https://ymotongpoo.hatenablog.com/entry/2020/07/17/093000&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>go</category>
      <category>trivia</category>
    </item>
    <item>
      <title>Search Go packages from navigation bar</title>
      <dc:creator>Yoshi Yamaguchi</dc:creator>
      <pubDate>Fri, 31 Jan 2020 19:45:49 +0000</pubDate>
      <link>https://forem.com/ymotongpoo/search-your-go-packages-from-navigation-bar-16d3</link>
      <guid>https://forem.com/ymotongpoo/search-your-go-packages-from-navigation-bar-16d3</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b0WjC4p---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0ft4qfyf3itpnm5h2x2z.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b0WjC4p---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0ft4qfyf3itpnm5h2x2z.jpg" alt="Find the package"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go team recently announced the new package search system, &lt;a href="https://blog.golang.org/pkg.go.dev-2020"&gt;pkg.go.dev, will take over the search on godoc.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It is often the case to use browsers for searching Go package on Google and godoc.org, but it seems it's time to create the shortcut for pkg.go.dev as the engineer who uses Go for daily basis. However, typing "pkg.go.dev" in the browser navigation takes some time and we'd like to reduce the typing effort if we can. So, let's do it!&lt;/p&gt;

&lt;p&gt;In Google Chrome, there's a setting for search engine, and there's a section titled "Manage search engines", where you can set up arbitrary URLs for querying something.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DmwjSovp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tie3yvkkk2099oqgy8w2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DmwjSovp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tie3yvkkk2099oqgy8w2.png" alt="Search engine setting"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You may already have a bunch of search engines registered, and here you can add another one for pkg.go.dev as the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lQnrOk5u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/03qv2uhsuyd4ax0jubu8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lQnrOk5u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/03qv2uhsuyd4ax0jubu8.png" alt="Add search engine"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this dialog, you need to put 3 settings, and especially important ones are "Keyword" and "Query URL".&lt;/p&gt;

&lt;p&gt;"Query URL" is straightforward. This is the URL template when you query anything with the search engine, and you can specify &lt;code&gt;%s&lt;/code&gt; as the placeholder for the query parameters or path name. In the case of pkg.go.dev, the value is &lt;code&gt;https://pkg.go.dev/search?q=%s&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;"Keyword" is what makes your productivity awesome. This is the shortcut name you want to type in the navigation bar of Google Chrome. With the combination of "keyword" and tab key, you can trigger the search engine. For instance, I used &lt;code&gt;pkg&lt;/code&gt; for the trigger keyword of pkg.go.dev, so if you type &lt;code&gt;pkg&lt;/code&gt; in the navigation bar and press tab key, then you'll see the following notation on the left side of the navigation bar:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iAdhuT7M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ey9hqvklmlr8bum8i7ou.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iAdhuT7M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ey9hqvklmlr8bum8i7ou.png" alt="Keyword triggering"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In that status, now you can type in Go package name you are looking for, such as &lt;code&gt;go.opentelemetry.io&lt;/code&gt;, then hit enter key. You can just type in a part of package names as well such as &lt;code&gt;error&lt;/code&gt; and so on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dlWp5UQx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jvwc46j2fnm7lw9n5oq1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dlWp5UQx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jvwc46j2fnm7lw9n5oq1.png" alt="Search result"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here you go! Now it got much easier to find package from the browser.&lt;/p&gt;

&lt;p&gt;Photo credit is by &lt;a href="https://www.thewritingreader.com/blog/2017/11/22/prompt-4079-so-many-packages/"&gt;https://www.thewritingreader.com/blog/2017/11/22/prompt-4079-so-many-packages/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>googlechrome</category>
      <category>packages</category>
    </item>
    <item>
      <title>Ignore ESLint rules on specific lines</title>
      <dc:creator>Yoshi Yamaguchi</dc:creator>
      <pubDate>Wed, 01 Jan 2020 23:28:11 +0000</pubDate>
      <link>https://forem.com/ymotongpoo/ignore-eslint-rules-on-specific-lines-4ej4</link>
      <guid>https://forem.com/ymotongpoo/ignore-eslint-rules-on-specific-lines-4ej4</guid>
      <description>&lt;p&gt;On writing codes for &lt;a href="https://developers.google.com/apps-script" rel="noopener noreferrer"&gt;Google Apps Script&lt;/a&gt; with &lt;a href="https://github.com/google/clasp" rel="noopener noreferrer"&gt;clasp&lt;/a&gt;, it is often the case you get warning from ESLint like "@typescript-eslint/no-unused-vars" on the functions because they are called from triggers in most cases.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fidsmipf3z8w33yyg3ey8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fidsmipf3z8w33yyg3ey8.png" alt="Warning message by ESLint" width="800" height="157"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For that, you can use inline comments to disable rule of ESLint as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;mp4Organize&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// eslint-disable-line @typescript-eslint/no-unused-vars&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://eslint.org/docs/2.13.1/user-guide/configuring#disabling-rules-with-inline-comments" rel="noopener noreferrer"&gt;ESLint: Configuring ESLint - Disabling Rules with Inline Comments&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>eslint</category>
    </item>
    <item>
      <title>Easiest and fastest way to run Docker image on GCE</title>
      <dc:creator>Yoshi Yamaguchi</dc:creator>
      <pubDate>Sun, 10 Nov 2019 10:37:23 +0000</pubDate>
      <link>https://forem.com/googlecloud/easiest-and-fastest-way-to-run-docker-image-on-gce-1a4e</link>
      <guid>https://forem.com/googlecloud/easiest-and-fastest-way-to-run-docker-image-on-gce-1a4e</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffrrp3wnx3kamr9di2omz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffrrp3wnx3kamr9di2omz.jpg" alt="Shipping container fast" width="700" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because I'm in Developer Relations team, it is often the case where I want to run some Docker image exposed to public for tentative demo purpose, in such as codelab, workshop or hackathon events.&lt;/p&gt;

&lt;p&gt;In those cases, I recommend to use &lt;a href="https://cloud.google.com/compute/" rel="noopener noreferrer"&gt;Google Compute Engine&lt;/a&gt; because it has the feature to &lt;a href="https://cloud.google.com/compute/docs/containers/deploying-containers" rel="noopener noreferrer"&gt;run Docker images on booting GCE instances&lt;/a&gt;.&lt;br&gt;
Using the feature, you can run and make some service public in 2 commands. One is for firewall setting, the other is GCE instance creation.&lt;/p&gt;

&lt;p&gt;For example, when you'd like to run &lt;a href="https://www.jaegertracing.io/docs/1.14/getting-started/" rel="noopener noreferrer"&gt;Jaeger all-in-one image&lt;/a&gt; and make it public Jaeger endpoint, you can run the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;gcloud compute firewall-rules create jaeger-rules &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="go"&gt;    --allow udp:5775,udp:6831,udp:6832,tcp:5778,tcp:16686,tcp:14268,tcp:9411 \
    --direction ingress \
    --priority 1000 \
    --target-tags jaeger

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;gcloud compute instances create-with-container jaeger-vm &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="go"&gt;    --container-image jaegertracing/all-in-one:1.14 \
    --boot-disk-size 30GB \
    --tags jaeger
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Photo credit by &lt;a href="https://www.marineinsight.com/guidelines/speed-of-a-ship-at-sea/" rel="noopener noreferrer"&gt;https://www.marineinsight.com/guidelines/speed-of-a-ship-at-sea/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gce</category>
      <category>gcp</category>
      <category>docker</category>
    </item>
  </channel>
</rss>
