{"@attributes":{"version":"2.0"},"channel":{"title":"DEV Community: Andy Gherna","description":"The latest articles on DEV Community by Andy Gherna (@argherna).","link":"https:\/\/dev.to\/argherna","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%2F5118%2F2c45bd71b39f5bbef84d376e09624e1a.jpeg","title":"DEV Community: Andy Gherna","link":"https:\/\/dev.to\/argherna"},"language":"en","item":[{"title":"The Java Preferences API Is a Little Thing That is a Huge Benefit","pubDate":"Fri, 25 May 2018 19:22:59 +0000","link":"https:\/\/dev.to\/argherna\/the-java-preferences-api-is-a-little-thing-thats-a-huge-benefit-13ac","guid":"https:\/\/dev.to\/argherna\/the-java-preferences-api-is-a-little-thing-thats-a-huge-benefit-13ac","description":"<h2>\n  \n  \n  Java Preferences Handle Most of what You Want to Do\n<\/h2>\n\n<p>Strong statement, but it's true. We've all come across different ways of managing configuration data. The Java Preferences API is one of those little things in the JDK that are often overlooked but are very useful. It handles a lot of the \"heavy lifting\" of managing external data and reduces your code's plumbing code.<\/p>\n\n<h2>\n  \n  \n  Where do I put Configuration Data?\n<\/h2>\n\n<p>I've been actively developing Java since 2002 and I still ask \"Where do I put configuration data?\". Usually the answer is \"Wherever your users want it dummy!\". There are so many choices, though. Which one do you want?<\/p>\n\n<h3>\n  \n  \n  A Plain Text File\n<\/h3>\n\n<p>A plain old <a href=\"https:\/\/docs.oracle.com\/javase\/10\/docs\/api\/java\/util\/Properties.html\">Java Properties<\/a> file has been my go-to choice for configuration for years (and it should be your's too). They're so easy to access and understand. But where do you put the file and how does your code read it? Do you put it on the classpath? Do you put it in an external directory? Do you change the code so that the application just \"knows\" where to look? Do you add support for fancy Url-style names for your file? <\/p>\n\n<p>These questions create a point of frustration for a lot of developers and customers. It'd be better if Java at least gave us a default that could be built off of like they do for the JDK Logging configuration where a configuration file can be stored and then overridden with a system property.<\/p>\n\n<p>Another question I've often asked is how often does a user actually change their configuration? My experience says the answer is very rarely, if ever. So while a configuration file is easily accessible and changable, that ease of access rendered moot if it's not going to be changed often (think <a href=\"https:\/\/www.martinfowler.com\/bliki\/Yagni.html\">YAGNI<\/a>).<\/p>\n\n<h3>\n  \n  \n  Other File Formats and Libraries\n<\/h3>\n\n<p>Sometimes you think need a different format from Properties so you try something else like XML, JSON, YAML, or whatever else (like the God-awful <a href=\"https:\/\/github.com\/hashicorp\/hcl#why\">HCL<\/a>). This is all well and good and there good \"reasons\" (rationalizations) for choosing a different file format. What you're doing though is adding to your user's <a href=\"https:\/\/en.wikipedia.org\/wiki\/Cognitive_load\">cognitive load<\/a>. A special configuation file format doesn't add anything to your application whatsoever. And if your customer won't be changing their configuration much after it's working, what's the point (see above)?<\/p>\n\n<p>But let's say that you have decided to use a different file format anyway. Now you need code to process it. You could write it. That'd be fine. Or would it? Code, debug, test, repeat till defects are gone. That's a waste of time that adds nothing to the <strong>functionality<\/strong> of your application.<\/p>\n\n<p>Ok, you say, I'll follow Josh Bloch's advice in Effective Java and just use a <a href=\"https:\/\/commons.apache.org\/proper\/commons-configuration\/index.html\">stable library<\/a> that's <a href=\"https:\/\/spring.io\/\">widely used<\/a> because the bugs have been flushed out by everyone. Using a library <strong>is great advice<\/strong>. Except now you've added a dependency to your application. If you depenedency graph is already complex, this is going to make it worse. There are lots of libraries to choose from for parsing configuration. Oh, and don't forget to write your tests for your configuration. When it comes to configuration your user couldn't care less if the application doesn't work right.<\/p>\n\n<h3>\n  \n  \n  How About in a Database or LDAP?\n<\/h3>\n\n<p>Don't. Now you've added another integration point\/dependency to your application.<\/p>\n\n<h2>\n  \n  \n  Man, You're Kind of a Jerk!\n<\/h2>\n\n<p>All of this tongue firmly planted in cheek discussion. Everyone has reasons for doing what they do. We all know that configuration should enhance your application or service, not be front and center. And there's an easy way to do that for Java-based applications. And that way is to use the <a href=\"https:\/\/docs.oracle.com\/javase\/10\/docs\/api\/java\/util\/prefs\/package-summary.html\">Preferences API<\/a> that's already part of the JDK (and has been since version 1.4) which is a solution to these common problems.<\/p>\n\n<h2>\n  \n  \n  So what are Java Preferences?\n<\/h2>\n\n<p>Java Preferences are data that is stored in a platform-specific way and accessed in a platform-agnostic way that is used to store configurations that seldom change. Confused? Let's break it down.<\/p>\n\n<p>Preference data is stored in a way that's best\/common for the platform the JVM is currently running on. For example, your JVM knows it's running on Windows so the concrete implementation of the <a href=\"https:\/\/docs.oracle.com\/javase\/10\/docs\/api\/java\/util\/prefs\/PreferencesFactory.html\">PreferencesFactory<\/a> will use the <a href=\"https:\/\/stackoverflow.com\/a\/32670299\/37776\">Windows Registry<\/a> to store its data. Other platforms will use what's appropriate for them. This is all OK because the API in the JDK that's used to access the Preference data is the same no matter what platform you're on, and it let's Java make up its own mind release-to-release how best to store these data. The details have been (very appropriately) abstracted away from you to let you concentrate on reading\/writing the data you need to make your application work.<\/p>\n\n<p>So now that you don't have to worry about accessing your platform's backing store, how do I change it? Well, since the data is stored in a way that is platform-specific this may mean you're not able to easily access it without operating system-specific tools. Most of the time that's fine, right? I mean, if you're constantly tweaking your application then that's one thing but if you just care about getting the thing set up and going without worrying about changing things run-to-run, then this is the best fit. For example, to read or change Preferences data in Windows, you'd likely use Regedit and navigate to the key that you wanted to change. Rather than doing that though, this API is easy enough to use and understand that you can <a href=\"https:\/\/github.com\/argherna\/Dotfiles\/blob\/master\/Scripts\/ImportPrefsTool.java\">write your own tools<\/a> <a href=\"https:\/\/github.com\/argherna\/Dotfiles\/blob\/master\/Scripts\/ExportPrefsTool.java\">to do the job for you<\/a> using the API and letting your JRE worry about the editing details.<\/p>\n\n<p>The best part about using and editing Preferences in this way is that there is a <a href=\"https:\/\/docs.oracle.com\/javase\/10\/docs\/api\/java\/util\/prefs\/Preferences.html\">standard format<\/a> for sharing Preferences data from platform-to-platform. This is totally editable outside the backing store and can be imported to another backing store with relative ease.<\/p>\n\n<h2>\n  \n  \n  Are These Just Key-Value Pairs or What?\n<\/h2>\n\n<p>Preferences are trees. The tree has roots with many nodes. The roots are for scoping the child nodes (either to the current <em>user<\/em> or the entire <em>system<\/em>). The nodes are names under the root. Each node can have another node or a map as children. Finally, a map has child entries that are the key-value pairs of data.<\/p>\n\n<p>The convention for nodes is to name them similar to unix-style paths, naming them with the fully-qualified class name (including the package). For example under the <em>user<\/em> root, there may be a node named <code>com\/github\/argherna\/LocalDirectoryServer<\/code> where each piece of the \"path name\" is a node under a node. At the lowest level node, there may be a map containing keys and values. The Preferences API lets you read them as <a href=\"https:\/\/docs.oracle.com\/javase\/10\/docs\/api\/java\/util\/prefs\/Preferences.html#get(java.lang.String,java.lang.String)\">Strings<\/a>, <a href=\"https:\/\/docs.oracle.com\/javase\/10\/docs\/api\/java\/util\/prefs\/Preferences.html#getBoolean(java.lang.String,boolean)\">booleans<\/a>, <a href=\"https:\/\/docs.oracle.com\/javase\/10\/docs\/api\/java\/util\/prefs\/Preferences.html#getInt(java.lang.String,int)\">integers<\/a>, <a href=\"https:\/\/docs.oracle.com\/javase\/10\/docs\/api\/java\/util\/prefs\/Preferences.html#getByteArray(java.lang.String,byte%5B%5D)\">byte arrays<\/a>  and other data types, and it requires you to set a default value if the key-value pair isn't in the map (Preferences don't like null values).<\/p>\n\n<p>There are limitations to the components of Preferences. They're meant to work on multiple platforms and as such they have to match the lowest common denominator for those platforms. So there's a maximum length for the name of a <a href=\"https:\/\/docs.oracle.com\/javase\/10\/docs\/api\/java\/util\/prefs\/Preferences.html#MAX_NAME_LENGTH\">node<\/a>, the name of a <a href=\"https:\/\/docs.oracle.com\/javase\/10\/docs\/api\/java\/util\/prefs\/Preferences.html#MAX_KEY_LENGTH\">key<\/a> , and the length for a <a href=\"https:\/\/docs.oracle.com\/javase\/10\/docs\/api\/java\/util\/prefs\/Preferences.html#MAX_VALUE_LENGTH\">value<\/a> as a string.<\/p>\n\n<h2>\n  \n  \n  Show Me an Example of this \"Platform-Agnostic\" API\n<\/h2>\n\n<p>When you compare reading and writing properties files to reading and writing Preferences, you notice that things you used to worry about just go away.<\/p>\n\n<h3>\n  \n  \n  Reading a Preference\n<\/h3>\n\n<p>The steps you should follow to access a Preference are:<\/p>\n\n<ol>\n<li>Get the root (either <em>user<\/em> or <em>system<\/em>).<\/li>\n<li>Get the node under your root.<\/li>\n<li>Read the key-value pair under the node.<\/li>\n<\/ol>\n\n<p>If the key-value pair isn't under the node, it will be created in the backing store.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight java\"><code><span class=\"nc\">Preferences<\/span> <span class=\"n\">myConnectionPrefs<\/span> <span class=\"o\">=<\/span> <span class=\"nc\">Preferences<\/span><span class=\"o\">.<\/span><span class=\"na\">userRoot<\/span><span class=\"o\">().<\/span><span class=\"na\">node<\/span><span class=\"o\">(<\/span><span class=\"s\">\"com\/github\/argherna\/MyApplication\/connections\"<\/span><span class=\"o\">);<\/span>\n<span class=\"nc\">String<\/span> <span class=\"n\">url<\/span> <span class=\"o\">=<\/span> <span class=\"n\">myConnectionPrefs<\/span><span class=\"o\">.<\/span><span class=\"na\">get<\/span><span class=\"o\">(<\/span><span class=\"s\">\"url\"<\/span><span class=\"o\">,<\/span> <span class=\"s\">\"http:\/\/example.com\"<\/span><span class=\"o\">);<\/span>\n\n<span class=\"c1\">\/\/ Now start doing stuff with the url.<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  Saving a Preference\n<\/h3>\n\n<p>Similar to above, the steps you should follow to save a Preference are:<\/p>\n\n<ol>\n<li>Get the root (either <em>user<\/em> or <em>system<\/em>).<\/li>\n<li>Get the node under your root.<\/li>\n<li>Save the key-value pair under the node.<\/li>\n<\/ol>\n\n<p>This part of the Preferences API represents a small <a href=\"https:\/\/en.wikipedia.org\/wiki\/Leaky_abstraction\">leaky abstraction<\/a> to me. The methods used to save data start with the verb <code>put<\/code> which is associated with the <a href=\"https:\/\/docs.oracle.com\/javase\/10\/docs\/api\/java\/util\/Map.html\">Map<\/a> interface. Perhaps that was intentional. If it were, I should be able to get the Map data structure under the node and operate directly on it, then set it back to the node and let the API persist the settings.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight java\"><code><span class=\"nc\">String<\/span> <span class=\"n\">newUrl<\/span> <span class=\"o\">=<\/span> <span class=\"s\">\"https:\/\/secure.example.com\/\"<\/span><span class=\"o\">;<\/span>\n<span class=\"nc\">Preferences<\/span> <span class=\"n\">myConnectionPrefs<\/span> <span class=\"o\">=<\/span> <span class=\"nc\">Preferences<\/span><span class=\"o\">.<\/span><span class=\"na\">userRoot<\/span><span class=\"o\">().<\/span><span class=\"na\">node<\/span><span class=\"o\">(<\/span><span class=\"s\">\"com\/github\/argherna\/MyApplication\/connections\"<\/span><span class=\"o\">);<\/span>\n\n<span class=\"c1\">\/\/ Save the newUrl.<\/span>\n<span class=\"n\">myConnectionPrefs<\/span><span class=\"o\">.<\/span><span class=\"na\">put<\/span><span class=\"o\">(<\/span><span class=\"s\">\"url\"<\/span><span class=\"o\">,<\/span> <span class=\"n\">newUrl<\/span><span class=\"o\">);<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  Other Operations\n<\/h3>\n\n<p>Preferences can be deleted, exported and imported. The export and import operations rely on the aforementioned file format linked in this post. You can check for children of nodes. You can check for values associated with a node. The API is fully capable of doing anything you can think of with a Preference.<\/p>\n\n<h2>\n  \n  \n  What else can this do?\n<\/h2>\n\n<p>The great part about the Prefrences API is that it's extensible. See the <a href=\"https:\/\/docs.oracle.com\/javase\/10\/docs\/api\/java\/util\/prefs\/Preferences.html\">Preferences API<\/a>. This means that if your IT shop centralizes its settings by putting them in a database or LDAP (as I groused about previously), you can write your own <a href=\"https:\/\/docs.oracle.com\/javase\/10\/docs\/api\/java\/util\/prefs\/PreferencesFactory.html\">PreferencesFactory<\/a> implementation that connnects to it and manages the read-write operations as well as the data structures. For nearly all purposes though, the default implementation is enough.<\/p>\n\n<h2>\n  \n  \n  What are the Drawbacks?\n<\/h2>\n\n<p>Fair question. There are the length limitations mentioned earlier. And that editing Preferences requires some tooling (either provided by your platform or yourself). <\/p>\n\n<p>One of the biggest drawbacks is that the Preferences API doesn't scale up very well. You can only associate 1 name-value pair with each node (no Collections-based values are allowed). But depending on how you use them, this should never be a concern.<\/p>\n\n<p>Knowing when to use them too is important. I use Preferences when:<\/p>\n\n<ul>\n<li>I can keep the amount of configuration small.<\/li>\n<li>I need to rely on the JRE to make the right decisions about where to store settings.<\/li>\n<li>The settings don't change often, if ever.<\/li>\n<li>The application can have an editor for Preferences built into it (including web applications) or I have tooling that lets me edit them.<\/li>\n<\/ul>\n\n<h2>\n  \n  \n  Do You Use these Yourself?\n<\/h2>\n\n<p>Yes I do. See some of the utilities in my <a href=\"https:\/\/github.com\/argherna\/Dotfiles\/tree\/master\/Scripts\">Dotfiles<\/a> repository. There you'll see the Preferences tools I wrote to support my applications. Also, see my project <a href=\"https:\/\/github.com\/argherna\/pike\">pike<\/a>. Preferences fit the way I develop some things. They aren't just for GUI applications. It's one of the little things the JDK has that does the job well.<\/p>\n\n","category":"java"},{"title":"Writing Java Command Line Tools is Cumbersome... Or is it???","pubDate":"Fri, 02 Mar 2018 03:06:01 +0000","link":"https:\/\/dev.to\/argherna\/writing-java-command-line-tools-is-cumbersome-or-is-it--p42","guid":"https:\/\/dev.to\/argherna\/writing-java-command-line-tools-is-cumbersome-or-is-it--p42","description":"<h2>\n  \n  \n  Simple Java Tools\n<\/h2>\n\n<p>The JDK comes with a lot of great command-line tools on its own that support development. But on every project I've ever done I find I need just a little more from a tool that I can't get from it which usually means I have to write my own. Every tool I write is for me and it's usually just enough to do the job.<\/p>\n\n<p>I write a lot of command-line tools to do my extra work. Most Java developers I work with hate the idea of writing a command-line Java tool. They have to be compiled, then they have to be run. Using <a href=\"https:\/\/maven.apache.org\/\">Maven<\/a> helps with the <code>exec:java<\/code> goal. Without Maven, you're writing long <code>javac<\/code> commands to compile, then a long <code>java<\/code> command to run it. But if you're careful and stick to what's in the JDK to write a small tool to get the job done, you can use <a href=\"https:\/\/gist.github.com\/swankjesse\/4742818\">a trick with the shell I saw a few years ago<\/a> to make writing Java a lot more like writing Python. <\/p>\n\n<h2>\n  \n  \n  A Simple Bash\/Java Example\n<\/h2>\n\n<p><a href=\"https:\/\/dev.to\/argherna\/bash-functions-and-aliases-for-the-beginning-docker-developer-d4\">Previously, I mentioned that I'm a huge fan of Bash<\/a>. All you need is a single Java source file and you can write something useful very fast. Consider this source file:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight java\"><code><span class=\"cm\">\/*bin\/mkdir -p \/tmp\/.java\/classes 2&gt; \/dev\/null\n\n# Compile the program.\n#\njavac -d \/tmp\/.java\/classes $0\n\n# Run the compiled program only if compilation succeeds.\n#\n[[ $? -eq 0 ]] &amp;&amp; java -cp \/tmp\/.java\/classes $(basename ${0%.*}) \"$@\"\nexit\n*\/<\/span>\n\n<span class=\"kd\">class<\/span> <span class=\"nc\">SimpleGreeting<\/span> <span class=\"o\">{<\/span>\n    <span class=\"kd\">public<\/span> <span class=\"kd\">static<\/span> <span class=\"kt\">void<\/span> <span class=\"nf\">main<\/span><span class=\"o\">(<\/span><span class=\"nc\">String<\/span><span class=\"o\">...<\/span> <span class=\"n\">args<\/span><span class=\"o\">)<\/span> <span class=\"o\">{<\/span>\n        <span class=\"nc\">System<\/span><span class=\"o\">.<\/span><span class=\"na\">out<\/span><span class=\"o\">.<\/span><span class=\"na\">println<\/span><span class=\"o\">(<\/span><span class=\"s\">\"Hello\"<\/span><span class=\"o\">);<\/span>\n    <span class=\"o\">}<\/span>\n<span class=\"o\">}<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Running this in the shell is as easy as:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>bash SimpleGreeting.java\nHello\n<span class=\"err\">$<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>What happened here? Why was that so easy?<\/p>\n\n<p>The answer is in the comment at the top. Shell scripts often start with a <a href=\"https:\/\/en.wikipedia.org\/wiki\/Shebang_(Unix)\">shebang<\/a> interpreter directive. A Java source file with this comment at the top runs the commands in bash.<\/p>\n\n<h2>\n  \n  \n  Breaking down the Interpreter Directive\n<\/h2>\n\n<p>It's easy to see what's going on here:<\/p>\n\n<ul>\n<li>Create a subdirectory under <code>\/tmp<\/code> redirecting output to <code>\/dev\/null<\/code> if the directory is already there (we don't care about an error message).<\/li>\n<li>Compile the source file and write the <code>.class<\/code> file in the target directory we just made.<\/li>\n<li>Run the <code>class<\/code> file from the directory it was just written to, stripping off the suffix of the source file. But only run it if it compiled.<\/li>\n<li>Exit the process with the return code of the <code>java<\/code> run.<\/li>\n<\/ul>\n\n<p>The best part about writing tools this way is that you can make changes to the code and \"run\" it again without worrying if compilation needs to happen. If you have an error, the compiler will tell you where it is and it won't attempt to run your program.<\/p>\n\n<h2>\n  \n  \n  Tips\n<\/h2>\n\n<p>Developing tools this efficiently means you should:<\/p>\n\n<ul>\n<li>Use as few dependencies as possible outside the JDK (ideally none)<\/li>\n<li>Keep your tools SIMPLE, short and in 1 source file.<\/li>\n<li>Run from the command line using <code>bash SourceFile.java &lt;args&gt;<\/code>.<\/li>\n<li>Avoid too much logic in the interpreter directive; but don't be afraid to use logic if you have to.<\/li>\n<\/ul>\n\n<h2>\n  \n  \n  Sample Tools\n<\/h2>\n\n<p>I've written some tools that have helped me out tremendously:<\/p>\n\n<ul>\n<li>Serving javadoc from the JDK docs zip file and javadoc jar files in your local Maven repository<\/li>\n<li>Dumping Base64\/raw secret keys from keystores<\/li>\n<li>Dumping a private key from a keystore<\/li>\n<li>Importing externally generated secret key into a keystore<\/li>\n<li>Checking LDAP\/JDBC connectivity<\/li>\n<\/ul>\n\n<p>There are tons of things you can do quickly using just the JDK. It may not have all the <a href=\"https:\/\/www.python.org\/dev\/peps\/pep-0206\/#batteries-included-philosophy\">batteries included<\/a> but it has all the kinds you could find without having to go to a specialty store.<\/p>\n\n<h2>\n  \n  \n  Acknowledgement\n<\/h2>\n\n<p>I'd like to again acknowledge <a href=\"https:\/\/github.com\/swankjesse\">Jessie Wilson<\/a> whose gist for <code>Rip.java<\/code> (linked above) inspired this post. He's a smart dude who likes to get things done quickly (obviously).<\/p>\n\n<p>My examples are in my <a href=\"https:\/\/github.com\/argherna\/Dotfiles\">Dotfiles GitHub repository<\/a>. Look in the Scripts directory and you'll find my tools along with all the other things I use.<\/p>\n\n","category":["java","bash"]},{"title":"Bash Functions and Aliases for the Beginning Docker Developer","pubDate":"Mon, 13 Nov 2017 15:49:06 +0000","link":"https:\/\/dev.to\/argherna\/bash-functions-and-aliases-for-the-beginning-docker-developer-d4","guid":"https:\/\/dev.to\/argherna\/bash-functions-and-aliases-for-the-beginning-docker-developer-d4","description":"<h2>\n  \n  \n  Where I'm Coming From\n<\/h2>\n\n<p>I run MacOS for work and Ubuntu for fun. Unix-y stuff has always appealed to me because of its composability and extensibility.<\/p>\n\n<p>I use Bash. Always have. It has plenty of features and is extensible. I used Zsh for a while, but found my way back to Bash after a time because it was important to me for my shell to match the script language I use (and I didn't grok Zsh scripting).<\/p>\n\n<p>Our team at work has recently started a process of migration to an off-premises vendor for hosting. Part of our deployment strategy involves deploying our services and applications to Docker which I've began learning mostly <a href=\"https:\/\/news.ycombinator.com\/item?id=10806244\">in anger<\/a>. There are new paradigms, commands, subcommands with switches and all kinds of extras that I've never had to think about before. And I've had to think about deployment and management of services more than ever before. DevOps has finally caught me.<\/p>\n\n<p>In this post, I don't describe what Docker is, how to build an image, etc. This is strictly about setting up something useful for learning and running the basic and (for me) most ran Docker commands quickly and easily.<\/p>\n\n<h2>\n  \n  \n  Why do this?\n<\/h2>\n\n<p>Developers have to know a lot about their tools. Sometimes we find ourselves running the same things over and over. Thankfully, modern shells have features that let us combine multiple commands into easy to remember mnemonics that are short and quick to type. Bash in particular has functions and aliases that can be defined in your profile to lighten the cognitive load of learning all these commands.<\/p>\n\n<p>I've started gathering the Docker bits into something that's usable for me and I'm sharing them here with you. What follows is a collection of Bash functions and aliases that I've found useful (that is, when I read my <code>.bash_history<\/code> and see the same command run more than 10 times) in working with Docker. <\/p>\n\n<h3>\n  \n  \n  Above All Else, Be Aware of Inconsistency\n<\/h3>\n\n<p>I learned quickly that <code>docker<\/code> and <code>docker-compose<\/code> are similar, but at the same time very different. They both share a number of subcommands with the same name. But be warned that the similarly named subcommands don't necessarily support the same options. The evolution of Docker has been exciting since it took the world by storm, but it's come at the cost of consistency in its commands.<\/p>\n\n<h3>\n  \n  \n  Function vs Alias\n<\/h3>\n\n<p>Functions and aliases in Bash are similar on the surface; you make a mnemonic for a long command. They are very different from each other though and it's important to understand why. See <a href=\"https:\/\/askubuntu.com\/a\/163895\/1641\">here<\/a> for a quick explanation of the difference between a Bash function and alias. If you've ever got a choice between defining an alias vs a function, the Bash manual says:<\/p>\n\n<blockquote>\n<p>For almost every purpose, shell functions are preferred over aliases.<\/p>\n<\/blockquote>\n\n<p>-- <a href=\"https:\/\/www.gnu.org\/software\/bash\/manual\/html_node\/Aliases.html\">Bash Reference Manual<\/a><\/p>\n\n<h3>\n  \n  \n  Naming Functions and Aliases\n<\/h3>\n\n<p>Naming is the hardest thing in the world for us as developers. When I am thinking about what to name a shell function, my checklist is:<\/p>\n\n<ul>\n<li>Length: has to be short (&lt; 20 characters if possible).<\/li>\n<li>Descriptive: has to concisely describe the action taken.<\/li>\n<\/ul>\n\n<p>The Docker functions below all start with the letter <code>d<\/code> (or <code>dc<\/code> for <code>docker-compose<\/code> commands) followed by the sometimes shortened subcommand followed by any other information. Normally I join compound words with an underscore but for the Docker functions I did not.<\/p>\n\n<p>Aliases should always be shorter names than a function. You can make them longer if you wish, but ~90% of the time I make them shorter.<\/p>\n\n<h3>\n  \n  \n  Function Parameter Checking\n<\/h3>\n\n<p>Shell functions can have parameters passed to them. I'll often have a check at the beginning of the functions I write that looks like this:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code>\n<span class=\"k\">if<\/span> <span class=\"o\">[<\/span> <span class=\"nv\">$# <\/span><span class=\"nt\">-eq<\/span> 0 <span class=\"o\">]<\/span><span class=\"p\">;<\/span> <span class=\"k\">then\n  <\/span><span class=\"nb\">echo<\/span> <span class=\"s1\">'Usage: $FUNCNAME ARG [ARG ...]'<\/span>\n  <span class=\"k\">return <\/span>1\n<span class=\"k\">fi<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>The <code>if<\/code> test is of course dependent on what the function needs. This snippet says \"if no arguments are passed to the function, print out a usage message and return 1\". The return code is important if you're using the function in another function or script. The <code>$FUNCNAME<\/code> variable is an internal Bash variable (reference below) that prints out the name of the currently running function. <\/p>\n\n<h2>\n  \n  \n  How I Use Functions\n<\/h2>\n\n<h3>\n  \n  \n  Shell into a Container\n<\/h3>\n\n<p>Sometimes things don't work as you had expected and you have to take a closer look at a container you've built to see what's going on. You'll need to do that with a shell (or as I've heard it said many times before, \"shell into\" the container). Docker's <code>exec<\/code> command will run a command. Since I want to start a shell in a specified container, the function below simplifies that for me:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"c\"># Run a bash shell in the specified container.<\/span>\n<span class=\"c\">#<\/span>\ndexbash<span class=\"o\">()<\/span> <span class=\"o\">{<\/span>\n  <span class=\"k\">if<\/span> <span class=\"o\">[<\/span> <span class=\"nv\">$# <\/span><span class=\"nt\">-ne<\/span> 1 <span class=\"o\">]<\/span><span class=\"p\">;<\/span> <span class=\"k\">then\n    <\/span><span class=\"nb\">echo<\/span> <span class=\"s2\">\"Usage: <\/span><span class=\"nv\">$FUNCNAME<\/span><span class=\"s2\"> CONTAINER_ID\"<\/span>\n    <span class=\"k\">return <\/span>1\n  <span class=\"k\">fi\n\n  <\/span>docker <span class=\"nb\">exec<\/span> <span class=\"nt\">-it<\/span> <span class=\"nv\">$1<\/span> \/bin\/bash\n<span class=\"o\">}<\/span>\n\n<span class=\"nb\">alias <\/span><span class=\"nv\">deb<\/span><span class=\"o\">=<\/span><span class=\"s1\">'dexbash'<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>This should be read as 'docker exec bash'. The <code>deb<\/code> alias shortens this to a nice 3-letter invocation. Why not name the function <code>deb<\/code>? You could. This is your shell and you're free to do what you want. <\/p>\n\n<p>When you're running multiple containers with <code>docker-compose<\/code> there's an <code>exec<\/code> command for it too, but be sure to leave off the <code>-it<\/code> options.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"c\"># Run a bash shell in the specified container (with docker-compose).<\/span>\n<span class=\"c\">#<\/span>\ndcexbash<span class=\"o\">()<\/span> <span class=\"o\">{<\/span>\n  <span class=\"k\">if<\/span> <span class=\"o\">[<\/span> <span class=\"nv\">$# <\/span><span class=\"nt\">-ne<\/span> 1 <span class=\"o\">]<\/span><span class=\"p\">;<\/span> <span class=\"k\">then\n    <\/span><span class=\"nb\">echo<\/span> <span class=\"s2\">\"Usage: <\/span><span class=\"nv\">$FUNCNAME<\/span><span class=\"s2\"> CONTAINER_ID\"<\/span>\n    <span class=\"k\">return <\/span>1\n  <span class=\"k\">fi\n\n  <\/span>docker-compose <span class=\"nb\">exec<\/span> <span class=\"nv\">$1<\/span> \/bin\/bash\n<span class=\"o\">}<\/span>\n\n<span class=\"nb\">alias <\/span><span class=\"nv\">dceb<\/span><span class=\"o\">=<\/span><span class=\"s1\">'dcexbash'<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Once you're in you can look for files, run probing commands, etc. just as you would in a normal shell. Of course, some of your favorite tools will be missing since this is a Docker container and it has to be kept small.<\/p>\n\n<h3>\n  \n  \n  Building and Tagging\n<\/h3>\n\n<p>Sometimes you want to build and sometimes you want to build <strong>and<\/strong> tag. This is an example of how to make your shell functions smart and demonstrates the power functions have over aliases:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"c\"># Runs Docker build and tag it with the given name.<\/span>\n<span class=\"c\">#<\/span>\ndbt<span class=\"o\">()<\/span> <span class=\"o\">{<\/span>\n  <span class=\"k\">if<\/span> <span class=\"o\">[<\/span> <span class=\"nv\">$# <\/span><span class=\"nt\">-lt<\/span> 1 <span class=\"o\">]<\/span><span class=\"p\">;<\/span> <span class=\"k\">then\n    <\/span><span class=\"nb\">echo<\/span> <span class=\"s2\">\"Usage <\/span><span class=\"nv\">$FUNCNAME<\/span><span class=\"s2\"> DIRNAME [TAGNAME ...]\"<\/span>\n    <span class=\"k\">return <\/span>1\n  <span class=\"k\">fi\n\n  <\/span><span class=\"nv\">ARGS<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"<\/span><span class=\"nv\">$1<\/span><span class=\"s2\">\"<\/span>\n  <span class=\"nb\">shift\n  <\/span><span class=\"k\">if<\/span> <span class=\"o\">[<\/span> <span class=\"nv\">$# <\/span><span class=\"nt\">-ge<\/span> 2 <span class=\"o\">]<\/span><span class=\"p\">;<\/span> <span class=\"k\">then\n    <\/span><span class=\"nv\">ARGS<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"<\/span><span class=\"nv\">$ARGS<\/span><span class=\"s2\"> -t <\/span><span class=\"nv\">$@<\/span><span class=\"s2\">\"<\/span>\n  <span class=\"k\">fi\n\n  <\/span>docker build <span class=\"nv\">$ARGS<\/span>\n<span class=\"o\">}<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>This will build or build and tag (with multiple tags) your container.<\/p>\n\n<h3>\n  \n  \n  Just Some Aliases\n<\/h3>\n\n<p>Remember, aliases are simply renamed commands with some flags. They take no parameters like functions do but they will append any flags and arguments you add to them on the command line. These are some aliases of my most-used Docker commands.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nb\">alias <\/span><span class=\"nv\">datt<\/span><span class=\"o\">=<\/span><span class=\"s1\">'docker attach'<\/span>\n<span class=\"nb\">alias <\/span><span class=\"nv\">dcb<\/span><span class=\"o\">=<\/span><span class=\"s1\">'docker-compose build'<\/span>\n<span class=\"nb\">alias <\/span><span class=\"nv\">dclogs<\/span><span class=\"o\">=<\/span><span class=\"s1\">'docker-compose logs'<\/span>\n<span class=\"nb\">alias <\/span><span class=\"nv\">dcu<\/span><span class=\"o\">=<\/span><span class=\"s1\">'docker-compose up'<\/span>\n<span class=\"nb\">alias <\/span><span class=\"nv\">ddiff<\/span><span class=\"o\">=<\/span><span class=\"s1\">'docker diff'<\/span>\n<span class=\"nb\">alias <\/span><span class=\"nv\">deb<\/span><span class=\"o\">=<\/span><span class=\"s1\">'dexbash'<\/span>\n<span class=\"nb\">alias <\/span><span class=\"nv\">dimg<\/span><span class=\"o\">=<\/span><span class=\"s1\">'docker images'<\/span>\n<span class=\"nb\">alias <\/span><span class=\"nv\">dins<\/span><span class=\"o\">=<\/span><span class=\"s1\">'docker inspect'<\/span>\n<span class=\"nb\">alias <\/span><span class=\"nv\">dps<\/span><span class=\"o\">=<\/span><span class=\"s1\">'docker ps'<\/span>\n<span class=\"nb\">alias <\/span><span class=\"nv\">drm<\/span><span class=\"o\">=<\/span><span class=\"s1\">'docker rm'<\/span>\n<span class=\"nb\">alias <\/span><span class=\"nv\">drmi<\/span><span class=\"o\">=<\/span><span class=\"s1\">'docker rmi'<\/span>\n<span class=\"nb\">alias <\/span><span class=\"nv\">drun<\/span><span class=\"o\">=<\/span><span class=\"s1\">'docker run'<\/span>\n<span class=\"nb\">alias <\/span><span class=\"nv\">dstart<\/span><span class=\"o\">=<\/span><span class=\"s1\">'docker start'<\/span>\n<span class=\"nb\">alias <\/span><span class=\"nv\">dstop<\/span><span class=\"o\">=<\/span><span class=\"s1\">'docker stop'<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  A Few (More) of My Favorite s\/Things\/Aliases\/\n<\/h3>\n\n<p>I noted that shell functions are preferable over shell aliases, but sometimes an alias is the right thing for the job. Take this gem for example:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"c\"># Credit to &lt;https:\/\/gist.github.com\/bastman\/5b57ddb3c11942094f8d0a97d461b430#remove-docker-images&gt;<\/span>\n<span class=\"nb\">alias <\/span><span class=\"nv\">dclimg<\/span><span class=\"o\">=<\/span><span class=\"s1\">'docker rmi $(docker images --filter \"dangling=true\" -q --no-trunc)'<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Imagine you're working on a Docker image and you're building it over and over. What you may not realize as a beginner is that the container that was previously built doesn't simply get overridden! It's still on your hard drive taking up space! When you run a <code>docker images<\/code> (or <code>dimg<\/code> as above if you noticed) you'll see images without a name. This little guy will clean all of those up for you in 1 command!<\/p>\n\n<p>Another thing I often will do is specify volumes where configuration files go locally so I can edit them quickly and easily. Depending on what I'm working on I may need to restart a container. This one below is a beaut for that:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"c\"># Credit to &lt;https:\/\/stackoverflow.com\/a\/21928864\/37776&gt;<\/span>\n<span class=\"nb\">alias <\/span><span class=\"nv\">drestartf<\/span><span class=\"o\">=<\/span><span class=\"s1\">'docker start $(docker ps -ql) &amp;&amp; docker attach $(docker ps -ql)'<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h2>\n  \n  \n  Conclusion\n<\/h2>\n\n<p>Bash is clearly my favorite shell, and not just for aliases and functions. Other shells have aliases and functions too and these can all be adapted for them. I hope you find these useful if you're using the command line when working with Docker. <\/p>\n\n<h2>\n  \n  \n  Docker &amp; Bash Hows\n<\/h2>\n\n<ul>\n<li><a href=\"https:\/\/www.gnu.org\/software\/bash\/manual\/html_node\/Shell-Functions.html\">Bash Reference Manual: Shell Functions<\/a><\/li>\n<li><a href=\"http:\/\/tldp.org\/LDP\/abs\/html\/internalvariables.html\">Internal Variables (Bash Shell)<\/a><\/li>\n<li><a href=\"https:\/\/zaiste.net\/posts\/removing_docker_containers\/\">Removing Docker Containers and Images<\/a><\/li>\n<\/ul>\n\n","category":["bash","docker"]},{"title":"Hi, I'm Andy Gherna","pubDate":"Wed, 22 Feb 2017 18:31:29 +0000","link":"https:\/\/dev.to\/argherna\/hi-im-andy-gherna","guid":"https:\/\/dev.to\/argherna\/hi-im-andy-gherna","description":"<p>I have been coding since 1997.<\/p>\n\n<p>You can find me on Twitter as <a href=\"https:\/\/twitter.com\/argherna\" rel=\"noopener noreferrer\">@argherna<\/a><\/p>\n\n<p>I live in St. Joseph IL.<\/p>\n\n<p>I work for Technology Services at the University of Illinois Urbana-Champaign<\/p>\n\n<p>I mostly program in these languages: Java, Python and JSON (ha ha! JSON isn't a programming language, nerd!).<\/p>\n\n<p>I am currently learning more about how TIF districts work.<\/p>\n\n<p>Nice to meet you.<\/p>\n\n","category":"introduction"}]}}