<?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>DEV Community: Jarek Przygódzki</title>
    <description>The latest articles on DEV Community by Jarek Przygódzki (@jarekprzygodzki).</description>
    <link>https://dev.to/jarekprzygodzki</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%2F61821%2Fa9c54e37-11f0-419f-b73a-9100e97e6010.png</url>
      <title>DEV Community: Jarek Przygódzki</title>
      <link>https://dev.to/jarekprzygodzki</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jarekprzygodzki"/>
    <language>en</language>
    <item>
      <title>Monitoring new process creation</title>
      <dc:creator>Jarek Przygódzki</dc:creator>
      <pubDate>Thu, 04 Jul 2019 20:39:36 +0000</pubDate>
      <link>https://dev.to/jarekprzygodzki/monitoring-new-process-creation-568</link>
      <guid>https://dev.to/jarekprzygodzki/monitoring-new-process-creation-568</guid>
      <description>&lt;p&gt;Monitoring process creation and termination events is a useful skill to have in you toolbox. This article consists of two parts. The first introduces exiting tools for diffrent platforms. The second explains how these tools work internally.&lt;/p&gt;

&lt;h1&gt;
  
  
  Introducing tools
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Linux
&lt;/h2&gt;

&lt;h3&gt;
  
  
  forkstat
&lt;/h3&gt;

&lt;p&gt;Forkstat monitors process fork(), exec() and exit() activity. It is mature and it's available in most distribution's repositories. Uses the Linux netlink connector to gather process activity.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Ubuntu\Debian
sudo apt install forkstat
sudo forkstat -e exec
Time     Event   PID Info   Duration Process
21:20:15 exec   3378                 sleep 10

sudo forkstat -e exec,exit
Time     Event   PID Info   Duration Process
21:21:30 exec   3384                 sleep 10
21:21:40 exit   3384      0  10.003s sleep 10

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Requires root privilege (or CAP_NET_ADMIN capability). Developed by &lt;a href="https://twitter.com/colinianking"&gt;Colin Ian King&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  execsnoop  (eBPF)
&lt;/h3&gt;

&lt;p&gt;execsnoop traces process execution. It works by dynamic tracing an execve kernel function. &lt;br&gt;
See the bcc &lt;a href="https://github.com/iovisor/bcc/blob/master/INSTALL.md"&gt;installation instructions&lt;/a&gt; for your OS. On Ubuntu, versions of bcc are available in the standard Ubuntu repository as of Ubuntu Bionic (18.04). The tools are installed in &lt;code&gt;/sbin&lt;/code&gt; (&lt;code&gt;/usr/sbin&lt;/code&gt; in Ubuntu 18.04) with a -bpfcc extension.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-get install bpfcc-tools linux-headers-$(uname -r)

sudo execsnoop-bpfcc 
PCOMM            PID    PPID   RET ARGS
sleep            5380   5379     0 /usr/bin/sleep 10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Originally created by &lt;a href="http://www.brendangregg.com/"&gt;Brendan Gregg&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  execsnoop
&lt;/h3&gt;

&lt;p&gt;Precedessor of eBPF based execsnoop. Still relevant because it has no dependecies other that awk and works on older Linux kernel versions (3.2+).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wget https://raw.githubusercontent.com/brendangregg/perf-tools/master/execsnoop \
    -O /usr/local/bin/execsnoop  &amp;amp;&amp;amp; chmod +x /usr/local/bin/execsnoop

execsnoop
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Does not work on many newer systems, try execsnoop (eBPF) first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Windows
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Process Monitor
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/sysinternals/downloads/procmon"&gt;&lt;em&gt;Process Monitor&lt;/em&gt;&lt;/a&gt;, part of &lt;em&gt;Sysinternals Suite&lt;/em&gt; is an advanced monitoring tool for Windows that can be used to keep track of process creation events.  Can be downloaded as standalone executable from project's website or installed with chocolatey package manager: &lt;code&gt;choco install procmon&lt;/code&gt;. Also part of &lt;a href="https://chocolatey.org/packages/sysinternals"&gt;Sysinternals Suite&lt;/a&gt; package. Primarily created by &lt;a href="https://en.wikipedia.org/wiki/Mark_Russinovich"&gt;Mark Russinovich&lt;/a&gt; and Bryce Cogswell&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VtMtj8M9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/rh1v2gogj4saq3hlnhxj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VtMtj8M9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/rh1v2gogj4saq3hlnhxj.png" alt="Process Monitor "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ProcMonX
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/zodiacon/ProcMonX"&gt;Process Monitor X&lt;/a&gt; (ProcMonX) is a alternative to ProcMon created by &lt;a href="https://twitter.com/zodiacon"&gt;Pavel Yosifovich&lt;/a&gt;. ProcMonX provides information on similar activities to ProcMon, but adds more events, such as networking, ALPC and memory. Can be downloaded as standalone executable &lt;a href="https://github.com/zodiacon/ProcMonX/releases/latest"&gt;from here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wwZhjPef--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/s2d7bpyl8tb78mbcdnl0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wwZhjPef--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/s2d7bpyl8tb78mbcdnl0.png" alt="Process Monitor X"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8MNBV83P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/qtp8mduq0kprkyz1cuuh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8MNBV83P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/qtp8mduq0kprkyz1cuuh.png" alt="Process Monitor X"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  PowerShell
&lt;/h3&gt;

&lt;p&gt;Microsoft Scripting Guy, &lt;a href="https://edwilson.com/"&gt;Ed Wilson&lt;/a&gt; shown that PowerShell can be used to monitor process creation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Register-CimIndicationEvent `
    -ClassName Win32_ProcessStartTrace `
    -SourceIdentifier "ProcessStarted"

Get-Event | `
    Select timegenerated, `
        @{L='Executable'; E = {$_.sourceeventargs.newevent.processname}}

TimeGenerated       Executable
-------------       ----------
12.06.2019 22:28:19 ps.exe
12.06.2019 22:29:13 bash.exe
12.06.2019 22:29:13 bash.exe
12.06.2019 22:29:13 bash.exe
12.06.2019 22:29:13 git.exe
12.06.2019 22:30:47 chrome.exe
12.06.2019 22:30:48 chrome.exe

# Cleanup
get-event | Remove-Event
Get-EventSubscriber | Unregister-Event

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;See &lt;a href="https://devblogs.microsoft.com/scripting/use-powershell-to-monitor-for-process-startup/"&gt;this&lt;/a&gt; article for details.&lt;/p&gt;

&lt;h2&gt;
  
  
  macOS
&lt;/h2&gt;

&lt;h3&gt;
  
  
  dtrace
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;sudo newproc.d&lt;/code&gt; will use &lt;a href="http://dtrace.org"&gt;DTrace&lt;/a&gt; to trace all new processes. It won't work if &lt;a href="https://support.apple.com/en-us/HT204899"&gt;System Integrity Protection&lt;/a&gt; is on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo newproc.d
dtrace: system integrity protection is on, some features will not be available

dtrace: failed to compile script /usr/bin/newproc.d: line 22: probe description proc:::exec-success does not match any probes. System Integrity Protection is on
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;El Capitan introduced a security mechanism called System Integrity Protection to help ensure that no malicious parties can modify the operating system and it severely limits what DTrace can do. &lt;/p&gt;

&lt;p&gt;SIP has to be partially diabled&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;csrutil enable --without dtrace # disable dtrace restrictions only
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Reboot and DTrace starts to work.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do these tools work
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Forkstat
&lt;/h3&gt;

&lt;p&gt;Forkstat uses the kernel &lt;a href="https://en.wikipedia.org/wiki/Netlink"&gt;Netlink&lt;/a&gt; connector interface to gather process activity.  It allows program to receive notifications of process events such as fork, exec, exit, core dump as well as changes to a process's name, UID, GID or SID  over a socket connection.&lt;/p&gt;

&lt;p&gt;With default parameters, forkstat will report fork, exec and exit events, but the -e option allows  to specify one or more of the fork, exec, exit, core, comm, clone, ptrce, uid, sid or all events.  When a fork event happens, forkstat will report the PID and process name of the parent and child, allowing one to easily identify where processes are originating. Forkstat  attempts to track the life time of a process and will log the duration of a processes when it exits where possible. Note that forkstat may miss events if the system is under heavy load. Netlink connector also requires root privilege (or using CAP_NET_ADMIN capability).&lt;/p&gt;

&lt;p&gt;Netlink is a Linux kernel IPC mechanism, enabling communication between a userspace process and the kernel, or multiple userspace processes. Netlink sockets are the primitive which enables this communication.&lt;br&gt;
&lt;code&gt;CONFIG_PROC_EVENTS&lt;/code&gt; kernel option  enables &lt;code&gt;Process Events Connector&lt;/code&gt; which exposes the process events to userland via a Netlink socket and was introduced in 2005 in &lt;a href="https://lwn.net/Articles/157150/"&gt;this&lt;/a&gt; patch by Matt Helsley.&lt;/p&gt;

&lt;p&gt;Forkstat's source code is &lt;a href="https://github.com/ColinIanKing/forkstat"&gt;here&lt;/a&gt; but it's very C-like in a sense that it manages to obfuscate relatively simple idea.&lt;/p&gt;

&lt;p&gt;To let userspace know about different process events we will have to &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;make a netlink socket and bind it &lt;/li&gt;
&lt;li&gt;send the &lt;code&gt;PROC_CN_MCAST_LISTEN&lt;/code&gt; message to the kernel to let it know we want to receive events&lt;/li&gt;
&lt;li&gt;receive events by reading datagrams from socket&lt;/li&gt;
&lt;li&gt;parse event data and extract the relevant process information
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sock, _ := unix.Socket(unix.AF_NETLINK,
    // used interchangeably with SOCK_RAW
    unix.SOCK_DGRAM, unix.NETLINK_CONNECTOR)
addr := &amp;amp;unix.SockaddrNetlink{
        Family: unix.AF_NETLINK, Groups: C.CN_IDX_PROC, Pid: uint32(os.Getpid())}
unix.Bind(sock, addr)
send(sock, C.PROC_CN_MCAST_LISTEN)
for {
    p := make([]byte, 4096)
    nbytes, from, _ := unix.Recvfrom(sock, p, 0)
    nlmessages, _ := syscall.ParseNetlinkMessage(p[:nbytes])
    for _, m := range nlmessages {
            if m.Header.Type == unix.NLMSG_DONE {
                // netlink uses the host byte order
                cnhdr := (*C.struct_cn_msg)(unsafe.Pointer(&amp;amp;m.Data[0]))
                ptr := uintptr(unsafe.Pointer(cnhdr))
                ptr += unsafe.Sizeof(*cnhdr)
                pe := (*C.struct_proc_event)(unsafe.Pointer(ptr))
                switch pe.what {
                case C.PROC_EVENT_EXEC:
                    e := (*C.struct_exec_proc_event)(unsafe.Pointer(&amp;amp;pe.event_data))
                    fmt.Printf("Process started: PID %d\n", e.process_pid)
                case C.PROC_EVENT_EXIT:
                    e := (*C.struct_exit_proc_event)(unsafe.Pointer(&amp;amp;pe.event_data))
                    fmt.Printf("Process exited: PID %d\n", e.process_pid)
                }
            }
            }
    }

}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;That's it! The only problem is that &lt;a href="https://github.com/torvalds/linux/blob/v5.0/include/uapi/linux/cn_proc.h#L80"&gt;&lt;code&gt;exec_proc_event&lt;/code&gt;&lt;/a&gt; contains little data. We could try to immediately read process information from &lt;code&gt;/proc/&amp;lt;PID&amp;gt;&lt;/code&gt; but that wouldn't be reliable (it's racy). There is a risk that by that time we read process information the process has already finished or even another one took its PID. Full example is &lt;a href="https://gist.github.com/jarek-przygodzki/0fd8b2c12a91d0141ca032794d08c05e"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  execsnoop  (eBPF)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/iovisor/bcc/blob/master/tools/execsnoop.py"&gt;execsnoop&lt;/a&gt; is part of BCC. It's a suite tools that use eBPF tracing:  infrastructure to dynamically instrument the kernel. It allows to define programs that run in kernel. Learn about eBPF &lt;a href="http://www.brendangregg.com/blog/2019-01-01/learn-ebpf-tracing.html"&gt;here&lt;/a&gt; or read &lt;a href="https://github.com/iovisor/bcc/blob/master/tools/execsnoop.py"&gt;execsnoop source code&lt;/a&gt;. The only downside is that these tools require new-ish kernel.&lt;/p&gt;
&lt;h3&gt;
  
  
  execsnoop
&lt;/h3&gt;

&lt;p&gt;Hack from Brendan Gregg's &lt;a href="https://github.com/brendangregg/perf-tools"&gt;perf-tools&lt;/a&gt; collection. It traces &lt;code&gt;stub_execve()&lt;/code&gt; or &lt;code&gt;do_execve(&lt;/code&gt;), and walks the &lt;code&gt;%si&lt;/code&gt; register as an array of strings. Check details on the author's blog &lt;a href="http://www.brendangregg.com/blog/2014-07-28/execsnoop-for-linux.html"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Process Monitor
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Process Monitor&lt;/em&gt;  (ProcMon) installs a kernel driver on startup which does the system-wide monitoring of userland processes. Driver API provides the kernel routine &lt;a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddk/nf-ntddk-pssetcreateprocessnotifyroutine"&gt;&lt;code&gt;PsSetCreateProcessNotifyRoutine&lt;/code&gt;&lt;/a&gt;/&lt;a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddk/nf-ntddk-pssetcreateprocessnotifyroutineex"&gt;&lt;code&gt;PsSetCreateProcessNotifyRoutineEx&lt;/code&gt;&lt;/a&gt; to allow software to monitor process creation and termination events in the Windows kernel. No code here, but &lt;a href="https://github.com/microsoft/Windows-driver-samples/blob/41c29cb92feff490270b4ce31f67d7baddecc457/general/obcallback/README.md"&gt;this&lt;/a&gt; example from  Windows Driver Kit (WDK) 10 is close to what we want.&lt;/p&gt;
&lt;h3&gt;
  
  
  ProcMonX
&lt;/h3&gt;

&lt;p&gt;ProcMonX uses &lt;a href="https://docs.microsoft.com/pl-pl/windows/win32/etw/event-tracing-portal"&gt;Event Tracing for Windows (ETW)&lt;/a&gt; (a diagnostics and logging mechanism that existed since Windows 2000) through &lt;a href="https://github.com/microsoft/perfview/blob/master/documentation/TraceEvent/TraceEventLibrary.md"&gt;Microsoft.Diagnostics.Tracing.TraceEvent&lt;/a&gt; library.&lt;/p&gt;
&lt;h3&gt;
  
  
  PowerShell
&lt;/h3&gt;

&lt;p&gt;PowerShell example uses WMI (&lt;a href="https://en.wikipedia.org/wiki/Windows_Management_Instrumentation"&gt;Windows Management Instrumentation&lt;/a&gt;) and &lt;a href="https://docs.microsoft.com/en-us/previous-versions/windows/desktop/krnlprov/win32-processstarttrace"&gt;&lt;code&gt;Win32_ProcessStartTrace&lt;/code&gt;&lt;/a&gt; event.&lt;/p&gt;

&lt;p&gt;Creating your own monitoring tool requires few lines of code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/*
 * csc procmon_wmi.cs
 */
using System;
using System.Management;

class ProcessMonitor
{
    static public void Main(String[] args)
    {
        var processStartEvent = 
            new ManagementEventWatcher("SELECT * FROM Win32_ProcessStartTrace");
        var processStopEvent = 
            new ManagementEventWatcher("SELECT * FROM Win32_ProcessStopTrace");

        processStartEvent.EventArrived += 
            new EventArrivedEventHandler(
                delegate (object sender, EventArrivedEventArgs e)
        {
            var processName = e.NewEvent.Properties["ProcessName"].Value;
            var processId = e.NewEvent.Properties["ProcessID"].Value;

            Console.WriteLine("{0} Process started. Name: {1} | PID: {2}", 
                DateTime.Now, processName, processId);
        });

        processStopEvent.EventArrived += 
            new EventArrivedEventHandler(
                delegate (object sender, EventArrivedEventArgs e)
        {
            var processName = e.NewEvent.Properties["ProcessName"].Value;
            var processId = e.NewEvent.Properties["ProcessID"].Value;

            Console.WriteLine("{0} Process stopped. Name: {1} | PID: {2}", 
                DateTime.Now, processName, processId);
        });

        processStartEvent.Start();
        processStopEvent.Start();

        Console.ReadKey();
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  macOS
&lt;/h2&gt;

&lt;h3&gt;
  
  
  dtrace
&lt;/h3&gt;

&lt;p&gt;DTrace is as dynamic tracing framework for Solaris, macOS and FreeBSD. You can learn more about &lt;a href="http://www.brendangregg.com/dtrace.html"&gt;DTrace Tools&lt;/a&gt; and read newproc.d source code &lt;a href="https://opensource.apple.com/source/dtrace/dtrace-168/DTTk/Proc/newproc.d.auto.html"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>linux</category>
      <category>windows</category>
      <category>macos</category>
    </item>
    <item>
      <title>Why is my Docker image so large?</title>
      <dc:creator>Jarek Przygódzki</dc:creator>
      <pubDate>Sun, 12 May 2019 12:20:45 +0000</pubDate>
      <link>https://dev.to/jarekprzygodzki/why-is-my-docker-image-so-large-3jja</link>
      <guid>https://dev.to/jarekprzygodzki/why-is-my-docker-image-so-large-3jja</guid>
      <description>&lt;p&gt;Keeping Docker images as small as possible has a lot of practical benefits. But even when following best practices &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use stripped-down base image&lt;/li&gt;
&lt;li&gt;utilize multi-stage builds&lt;/li&gt;
&lt;li&gt;don't install what you don't need&lt;/li&gt;
&lt;li&gt;optimize build context&lt;/li&gt;
&lt;li&gt;minimize number of layers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;some images end up being larger than they have to be inadvertently including files that are not necessary .&lt;/p&gt;

&lt;h1&gt;
  
  
  How to troubleshoot issues with image size?
&lt;/h1&gt;

&lt;p&gt;Image filesystem changes are tracked in layers. Each layer is the the representation of the file system changes for each instruction in Dockerfile. Layers of a Docker image are essentially  files generated from running some command during &lt;code&gt;docker build&lt;/code&gt; in ephemeral intermediate container.&lt;/p&gt;

&lt;p&gt;In the past, I used to perform &lt;code&gt;docker history &amp;lt;image name&amp;gt;&lt;/code&gt; to view all the layers that make up the image, manually extract suspicious layers and inspect their content. It worked, but it was tedious.&lt;/p&gt;

&lt;h1&gt;
  
  
  Dive
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/wagoodman/dive"&gt;Dive&lt;/a&gt; is a new tool for exploring a Docker images, inspecting layer contents and discovering ways to shrink your Docker image size - all that in a nice text-based user interface.&lt;/p&gt;

&lt;p&gt;I recently used it to diagnose an unexpected image size growth caused by change of  file ownership &amp;amp; permissions. One of the instructions in &lt;code&gt;jboss/wildfly&lt;/code&gt; based Dockerfile was &lt;code&gt;chown -R jboss:jboss /opt/jboss/wildfly/&lt;/code&gt;. It looks innocent, but these files are originally owned by &lt;em&gt;jboos:root&lt;/em&gt;. Docker doesn't know what changes have happened inside a layer, only which files are affected.  As such, this will cause Docker to create a new layer, replacing all those files (same content as &lt;em&gt;/opt/jboss/wildfly/&lt;/em&gt; but with with new ownership), adding hundreds of megabytes to image size. &lt;/p&gt;

&lt;h1&gt;
  
  
  Resources
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/wagoodman/dive"&gt;Dive GitHub Page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/develop/develop-images/dockerfile_best-practices/"&gt;Best practices for writing Dockerfiles&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>docker</category>
      <category>dive</category>
    </item>
    <item>
      <title>A curious case of slow Docker image builds</title>
      <dc:creator>Jarek Przygódzki</dc:creator>
      <pubDate>Fri, 31 Aug 2018 19:36:18 +0000</pubDate>
      <link>https://dev.to/jarekprzygodzki/a-curious-case-of-slow-docker-image-builds-2o7k</link>
      <guid>https://dev.to/jarekprzygodzki/a-curious-case-of-slow-docker-image-builds-2o7k</guid>
      <description>&lt;h1&gt;
  
  
  Investigating slow Docker image builds
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;A rather short but hopefully interesting troubleshooting story that happened recently.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Lately, I was investigating a case of slow Docker image builds on CI server (Oracle Linux 7.5 with Docker devicemapper storage driver in direct-lvm mode). Each operation which altered layers (ADD, COPY, RUN) took up to 20 seconds - the larger the image, the longer. &lt;/p&gt;

&lt;p&gt;A typical way of dealing with with apparently stuck program is collecting thread stack traces. Or goroutines' stacktraces in the case of the Go application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dump of dockerd
&lt;/h2&gt;

&lt;p&gt;Docker deamon will write goroutines stacktraces to a file named &lt;code&gt;goroutine-stacks-&amp;lt;datetime&amp;gt;.log&lt;/code&gt; after receving a SIGUSR1 signal (&lt;a href="https://github.com/docker/docker-ce/blob/18.09/components/engine/daemon/debugtrap_unix.go#L16" rel="noopener noreferrer"&gt;engine/daemon/debugtrap_unix.go&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;pkill -SIGUSR1 dockerd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A quick analysis showed that almost all the time was spent in &lt;code&gt;NaiveDiffDriver.Diff&lt;/code&gt;. Here it is one of the dumps&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h2&gt;
  
  
  What is a NaiveDiffDriver and why is it naive?
&lt;/h2&gt;

&lt;p&gt;Docker image consist of immutable layers that are based on ordered root filesystem changes (and some metadata). Storage driver implementation handles merging of layers into a single mount point and provides a writable layer (called the “container layer”) on top of the underlying layers. All filesystem changes are written to this thin writable container layer. Each time a container is committed (manually or as part of building a Dockerfile), the storage driver needs to provide a list of modified files and directories relative to the base image to create a new layer. Some drivers keep track of these changes at run time and can generate that list easily but for drivers with no native handling for calculating changes Docker provides &lt;code&gt;NaiveDiffDriver&lt;/code&gt;. This driver produces a list of changes between current container filesystem  and its parent layer by recursively traversing both directory trees and comparing file metadata. This operation is expensive for big images with many files and directories. See &lt;a href="https://integratedcode.us/2016/08/30/storage-drivers-in-docker-a-deep-dive/" rel="noopener noreferrer"&gt;here&lt;/a&gt; and &lt;a href="https://portworx.com/lcfs-speed-up-docker-commit/" rel="noopener noreferrer"&gt;here&lt;/a&gt; for in depth description of storage drivers in Docker.&lt;/p&gt;

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

&lt;p&gt;The Device Mapper storage driver is good choice for running container in production on Red Hat and it's derivatives but not for building images because it's lack of native diff support. After some thought I choose &lt;a href="https://docs.docker.com/storage/storagedriver/overlayfs-driver/" rel="noopener noreferrer"&gt;overlay2&lt;/a&gt; as a replacement. It turned out that native diff support in overlay2 in incompatible with &lt;a href="https://github.com/torvalds/linux/blob/v4.18/fs/overlayfs/Kconfig#L13" rel="noopener noreferrer"&gt;OVERLAY_FS_REDIRECT_DIR&lt;/a&gt; option enabled in modern kernels: &lt;a href="https://github.com/moby/moby/pull/34342" rel="noopener noreferrer"&gt;storage driver falls back to NaiveDiffDriver with a waring when it's detected&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;# https://github.com/docker/docker-ce/blob/18.09/components/engine/daemon/graphdriver/overlay2/overlay.go#L287
Not using native diff for overlay2, this may cause degraded performance for building images: kernel has CONFIG_OVERLAY_FS_REDIRECT_DIR enabled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The workaround I came up with is to disable &lt;em&gt;overlay_redirect_dir&lt;/em&gt; option in overlay module&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo 'options overlay redirect_dir=off' &amp;gt; /etc/modprobe.d/disable_overlay_redirect_dir.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which finally enables native diffs&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Storage Driver: overlay2
 Backing Filesystem: xfs
 Supports d_type: true
 Native Overlay Diff: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No more time an CPU cycles lost computing layer diffs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus
&lt;/h2&gt;

&lt;p&gt;I created &lt;a href="https://github.com/jarek-przygodzki/docker-image-build-times" rel="noopener noreferrer"&gt;a few virtual machines&lt;/a&gt; to confirm the source of the problem and to work on the solution. &lt;/p&gt;

&lt;p&gt;Nice think about Go is that it integrates pprof into the standard library and dockerd enables pprof/debug endpoints by default since 17.07.0-ce (2017-08-29) (earlier the profiler api was only available in debug mode: --debug/-D, &lt;a href="https://github.com/moby/moby/pull/32453" rel="noopener noreferrer"&gt;Enable pprof/debug endpoints by default #32453&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Docker in flames&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go-torch --file docker-build.svg --title="docker build" \
    --url http://localhost:2375
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fjarek-przygodzki%2Fdocker-image-build-times%2Fraw%2Fmaster%2Fassets%2Fdocker-build-devicemapper.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fjarek-przygodzki%2Fdocker-image-build-times%2Fraw%2Fmaster%2Fassets%2Fdocker-build-devicemapper.png" alt="docker build flame graph"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Docker daemon is spending most of its time in &lt;code&gt;NaiveDiffDriver.Diff&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go-torch --file docker-build-inversed.svg --inversed --title="docker build" \
    --url http://localhost:2375
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fjarek-przygodzki%2Fdocker-image-build-times%2Fraw%2Fmaster%2Fassets%2Fdocker-build-devicemapper-inversed.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fjarek-przygodzki%2Fdocker-image-build-times%2Fraw%2Fmaster%2Fassets%2Fdocker-build-devicemapper-inversed.png" alt="docker build flame graph inversed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;... doing syscalls.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devicemapper</category>
      <category>overlay2</category>
      <category>linux</category>
    </item>
    <item>
      <title>Generating JVM memory dumps from JRE</title>
      <dc:creator>Jarek Przygódzki</dc:creator>
      <pubDate>Tue, 28 Aug 2018 19:14:59 +0000</pubDate>
      <link>https://dev.to/jarekprzygodzki/generating-jvm-memory-dumps-from-jre-h8c</link>
      <guid>https://dev.to/jarekprzygodzki/generating-jvm-memory-dumps-from-jre-h8c</guid>
      <description>&lt;h1&gt;
  
  
  Generating JVM memory dumps from JRE on Linux/Windows/OSX
&lt;/h1&gt;

&lt;p&gt;Generating a JVM heap memory dump with JDK is straightforward as almost every Java developer knows about jmap and jcmd tools that come with the JDK. But what about JRE?&lt;/p&gt;

&lt;p&gt;Some people think you &lt;a href="https://stackoverflow.com/questions/24213491/how-do-i-produce-a-heap-dump-with-only-a-jre"&gt;need JDK&lt;/a&gt;, or at least &lt;a href="https://medium.com/@chamilad/extracting-memory-and-thread-dumps-from-a-running-jre-based-jvm-26de1e37a080"&gt;part of it&lt;/a&gt;, but that's not true. The answer lies in &lt;a href="https://github.com/apangin/jattach"&gt;jattach&lt;/a&gt;, a tool to send commands to JVM via Dynamic Attach mechanism created by JVM hacker Andrei Pangin (&lt;a href="https://twitter.com/andreipangin"&gt;@AndreiPangin&lt;/a&gt;). It's tiny (24KB), works with just JRE and supports Linux containers. &lt;/p&gt;

&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;Most of the time it comes down to downloading a single file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wget -L -O /usr/local/bin/jattach \
    https://github.com/apangin/jattach/releases/download/v1.5/jattach &amp;amp;&amp;amp; \
    chmod +x /usr/local/bin/jattach
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can then send &lt;code&gt;dumpheap&lt;/code&gt; command do JVM process&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jattach PID-OF-JAVA dumpheap &amp;lt;path to heap dump file&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;e.g&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;java_pid=$(pidof -s java) &amp;amp;&amp;amp; \
    jattach $java_pid dumpheap /tmp/java_pid$java_pid-$(date +%Y-%m-%d_%H-%M-%S).hprof
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How does it work?
&lt;/h2&gt;

&lt;p&gt;Built-in JDK utilities like jmap and jstack have two execution modes: cooperative and forced. In normal cooperative mode these tools use Dynamic Attach Mechanism to connect to the target VM. The requested command is then executed by the target VM in it's own process. This mode is used by jattach. &lt;/p&gt;

&lt;p&gt;The forced mode (jmap -F, jstack -F) works differently. The tool suspends the target process and then reads the process memory using Serviceability Agent. See &lt;a href="https://stackoverflow.com/questions/26140182/running-jmap-getting-unable-to-open-socket-file/35963059#35963059"&gt;this&lt;/a&gt; for details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker
&lt;/h2&gt;

&lt;p&gt;Prior to  Java 10 jmap, jstack and jcmd could not attach from a process on the host machine to a JVM running inside a Docker container because of how the attach mechanism interacts with pid and mount namespaces. Java 10 &lt;a href="https://bugs.openjdk.java.net/browse/JDK-8179498"&gt;fixes this&lt;/a&gt; by the JVM inside the container finding its PID in the root namespace and using this to watch for a JVM attachment.&lt;/p&gt;

&lt;p&gt;Jattach supports containers and is compatible with earlier versions of JVM - all we need is process id in host PID namespace. How can we get it?&lt;/p&gt;

&lt;p&gt;If JVM is the main process of a container (PID 1), the needed information is included in &lt;code&gt;docker inspect&lt;/code&gt; output&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cid=&amp;lt;container name or id&amp;gt;
host_pid=$(docker inspect --format {{.State.Pid}} $cid)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it's not? Then things become more interesting. The easiest way that I know of is to use /proc/PID/sched - kernel scheduling statistics.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cid=&amp;lt;container name or id&amp;gt;
docker exec -it $cid bash -c 'cat /proc/$(pidof -s java)/sched'

java (8251, #threads: 127)
------------------------------------------------------------------------
se.exec_start                                :        275669.207074
se.vruntime                                  :            80.606203
se.sum_exec_runtime                          :            57.897264
nr_switches                                  :                  157
nr_voluntary_switches                        :                  149
nr_involuntary_switches                      :                    8
se.load.weight                               :                 1024
se.avg.load_sum                              :              8883079
se.avg.util_sum                              :                 4424
se.avg.load_avg                              :                  181
se.avg.util_avg                              :                   90
se.avg.last_update_time                      :         275669207074
policy                                       :                    0
prio                                         :                  120
clock-delta                                  :                   52
mm-&amp;gt;numa_scan_seq                            :                    0
numa_migrations, 0
numa_faults_memory, 0, 0, 1, 0, -1
numa_faults_memory, 1, 0, 0, 0, -1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For us interesting is the first line of the output (format defined in &lt;a href="https://github.com/torvalds/linux/blob/v4.18/kernel/sched/debug.c#L877"&gt;kernel/sched/debug.c#L877&lt;/a&gt;. Desired PID can be extract with a little bit of shell scripting&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker exec -it $cid sh -c 'head -1 /proc/$(pidof -s java)/sched | grep -P "(?&amp;lt;=\()\d+" -o'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When target container is bare (no shell, no cat, no nothing), nsenter is a possible alternative to &lt;code&gt;docker exec&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;host_pid=$(docker inspect --format {{.State.Pid}} &amp;lt;container name or id&amp;gt;)
nsenter --target $host_pid  --pid --mount  sh -c 'cat /proc/$(pidof -s java)/sched'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What can go wrong?
&lt;/h2&gt;

&lt;p&gt;Jattach from project's release page is linked against glibc so it &lt;a href="https://wiki.alpinelinux.org/wiki/Running_glibc_programs"&gt;most likely&lt;/a&gt; won't work on Alpine Linux. But it is not too hard to make it work.&lt;/p&gt;

</description>
      <category>jvm</category>
      <category>jre</category>
      <category>jattach</category>
      <category>docker</category>
    </item>
  </channel>
</rss>
