<?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: David Sabine</title>
    <description>The latest articles on DEV Community by David Sabine (@davidsabine).</description>
    <link>https://dev.to/davidsabine</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%2F460717%2F1d71af36-2425-4490-9697-d385d91e74ae.png</url>
      <title>DEV Community: David Sabine</title>
      <link>https://dev.to/davidsabine</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davidsabine"/>
    <language>en</language>
    <item>
      <title>SQL Joins Infographic</title>
      <dc:creator>David Sabine</dc:creator>
      <pubDate>Thu, 12 Oct 2023 14:05:49 +0000</pubDate>
      <link>https://dev.to/davidsabine/sql-joins-infographic-31bc</link>
      <guid>https://dev.to/davidsabine/sql-joins-infographic-31bc</guid>
      <description>&lt;p&gt;Credit to C.L. Moffatt, 2008.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xW18Imjn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jrjx6xrv7baa13d816rq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xW18Imjn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jrjx6xrv7baa13d816rq.jpg" alt="Image description" width="800" height="629"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Joining tables in a SQL query is a powerful skill. This info graphic illustrates how each type of join behaves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LEFT JOIN&lt;/li&gt;
&lt;li&gt;RIGHT JOIN&lt;/li&gt;
&lt;li&gt;INNER JOIN&lt;/li&gt;
&lt;li&gt;FULL OUTER JOIN&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>sql</category>
      <category>database</category>
    </item>
    <item>
      <title>ASP From the Trenches — Hey Bartender, Make It A Double!</title>
      <dc:creator>David Sabine</dc:creator>
      <pubDate>Tue, 10 Oct 2023 01:51:56 +0000</pubDate>
      <link>https://dev.to/davidsabine/asp-from-the-trenches-hey-bartender-make-it-a-double-5em4</link>
      <guid>https://dev.to/davidsabine/asp-from-the-trenches-hey-bartender-make-it-a-double-5em4</guid>
      <description>&lt;p&gt;REPRINT FROM MAY, 2003.&lt;/p&gt;




&lt;p&gt;If you are lucky enough to never have to work on legacy code, leave this page.&lt;/p&gt;

&lt;p&gt;Otherwise, stay for some tips when working with Classic ASP.&lt;/p&gt;




&lt;p&gt;Working with dates in ASP/VBScript makes me want to bludgeon my skull with a blunt object. Especially in multi-lingual environments.&lt;/p&gt;

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

&lt;p&gt;I really mean this: &lt;em&gt;avoid using dates whenever possible!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Instead, use a data-type that VBScript will (almost) never screw up: the “DOUBLE”.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tools – Choose Wisely
&lt;/h2&gt;

&lt;p&gt;VBScript has built-in functions to help manage dates, numbers, currencies, and other data types. If you are reading this article, it’s because you’ve realized those built-in functions appear to be fundamentally flawed.&lt;/p&gt;

&lt;p&gt;VBScript includes the following functions which are intended to manage date/time data:&lt;/p&gt;

&lt;h3&gt;
  
  
  IsDate()
&lt;/h3&gt;

&lt;p&gt;This is supposed to help you determine if a variable is of type “Date”. It’s inherently flawed and its output can’t be trusted.&lt;/p&gt;

&lt;h3&gt;
  
  
  CDate()
&lt;/h3&gt;

&lt;p&gt;Intended to convert a variable of type “(something)” to a variable of type “Date” but it can lie and is sometimes lazy. You must not trust it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Second(), Minute(), Hour(), Day(), Weekday(), WeekdayName(), Month(), MonthName(), Year(), Date(), Time(), Now()
&lt;/h3&gt;

&lt;p&gt;These produce – supposedly – a value of type “Date” based on the system’s current date/time. I recommend you ignore all of them except “Now()”!&lt;/p&gt;

&lt;h3&gt;
  
  
  DateAdd(), DateDiff(), DatePart(), DateSerial(), DateValue(), TimeSerial(), TimeValue()
&lt;/h3&gt;

&lt;p&gt;More date manipulation. Frankly, I’ve found only DateAdd() and DateDiff() to be of any real help and the others can be avoided altogether.&lt;/p&gt;

&lt;h3&gt;
  
  
  FormatDateTime()
&lt;/h3&gt;

&lt;p&gt;A great function! But it has to be treated carefully.&lt;/p&gt;

&lt;h2&gt;
  
  
  What do you mean, “flawed”?
&lt;/h2&gt;

&lt;p&gt;I mean that VBScript is not a strongly-typed language — it’s loose and happily changes our sloppy variables from strings to dates to numbers and back. There are implicit data-type conversions happening all the time – regardless of how careful a programmer tries to be.&lt;/p&gt;

&lt;p&gt;And the built-in functions above only work reliably when the arguments are a predictable data-type; they’ll break or produce unexpected results if they must perform implicit data-type conversion. &lt;em&gt;That’s the tragic flaw and there’s no method to enforce strong data-types.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Do These Functions Work?
&lt;/h2&gt;

&lt;p&gt;Yes and no. As far as I can tell, these functions work well if your application resides and operates in a very cohesive and structured environment. If your database, your application and your web server all reside on a single computer (or multiple computers with identical Regional Settings). But if your system’s Regional Settings change or if you utilize VBScript’s “SetLocale()” function or alter the “.CodePage” or “.LCID” properties of ASP’s “Response” object, then you should expect problems and the above functions aren’t reliable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The solution is CDbl(), more on that later…&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-Lingual Settings
&lt;/h2&gt;

&lt;p&gt;The problems are amplified in multi-lingual situations. Imagine the following scenario:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;VBScript is decidedly a “US English” language.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Perhaps your ASP application will be hosted on a web server in France so functions like CBool() produce “VRAI/FAUX” instead of “TRUE/FALSE” – &lt;em&gt;I didn’t know that until my app broke on a server in France!&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The HTML pages will be written entirely in Turkish – but the client wants to display currencies and dates in “British Pounds” and “en-gb” instead of Euro or the Turkish Lira.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Perhaps the application will connect to a SQL database hosted in España.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And perhaps the users of the application will be scattered around the globe and speak all 6800 known languages and they don’t want to have to &lt;em&gt;think&lt;/em&gt; about whether “DD” comes before or after the “MM” and whether “YYYY” should be abbreviated to just “YY” and separated with a “/ - : .” and so on.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I’m sure by now you understand the depth of the problem and you’re starting to wonder if you can afford the bartender’s tab.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problems
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is a “Date” Really a Date?
&lt;/h3&gt;

&lt;p&gt;The table below demonstrates how the date functions usually operate just fine. Basically I will assigned a VBScript variable a value of “Now()” and then pass that information through other date-related functions. The script engine will correctly interpret the value as a “Date” data-type even in various locales.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Test #1
&lt;/h3&gt;

&lt;p&gt;Let’s start with a value that we know is a date: “Now()”&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;%
 SetLocale("en-ca")
 dim theDateVariable
 theDateVariable = Now()
%&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;“Now()” at the time of this writing is: 03/May/2003 3:47:29 PM&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TypeName(theDateVariable) = Date
IsDate(theDateVariable) = True
FormatDateTime(theDateVariable,0) = 03/05/2003 3:47:29 PM 'vbGeneralDate
FormatDateTime(theDateVariable,1) = May 3, 2003 'vbLongDate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;SetLocale(“es-es”)&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TypeName(theDateVariable) = Date
IsDate(theDateVariable) = True
FormatDateTime(theDateVariable,0) = 03/05/2003 15:47:29 'vbGeneralDate
FormatDateTime(theDateVariable,1) = sábado, 03 de mayo de 2003 'vbLongDate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;SetLocale(“en-us”)&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TypeName(theDateVariable) = Date
IsDate(theDateVariable) = True
FormatDateTime(theDateVariable,0) = 5/3/2003 3:47:29 PM 'vbGeneralDate
FormatDateTime(theDateVariable,1) = Saturday, May 03, 2003
‘vbLongDate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;SetLocale(“tr”)&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TypeName(theDateVariable) = Date
IsDate(theDateVariable) = True
FormatDateTime(theDateVariable,0) = 03.05.2003 15:47:29 'vbGeneralDate
FormatDateTime(theDateVariable,1) = 03 Mayis 2003 Cumartesi 'vbLongDate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All is well! It all checks out and there are no apparent problems. &lt;/p&gt;

&lt;p&gt;Below is the same set of tests, but this time I’ll define the value of our variable manually:&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Test #2
&lt;/h3&gt;

&lt;p&gt;I’ll set the variable to the 3rd of May and ensure that it’s a valid “Date” data-type by using the CDate() function…then I’ll pass it through the same tests as above.&lt;/p&gt;

&lt;p&gt;This will work because I explicitly cast the variable as a “Date” while in the original locale. I set the locale to “en-ca” &lt;strong&gt;and&lt;/strong&gt; give the script a valid Canadian date/time value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;%
 SetLocale("en-ca")
 dim theDateVariable
 theDateVariable = CDate("03/05/2003 3:47:29 PM")
%&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TypeName(theDateVariable) = Date
IsDate(theDateVariable) = True
FormatDateTime(theDateVariable,0) = 03/05/2003 3:47:29 PM 'vbGeneralDate
FormatDateTime(theDateVariable,1) = May 3, 2003 'vbLongDate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;SetLocale(“es-es”)&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TypeName(theDateVariable) = Date
IsDate(theDateVariable) = True
FormatDateTime(theDateVariable,0) = 03/05/2003 15:47:29 'vbGeneralDate
FormatDateTime(theDateVariable,1) = miércoles, 03 de mayo de 2003 'vbLongDate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;SetLocale(“en-us”)&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TypeName(theDateVariable) = Date
IsDate(theDateVariable) = True
FormatDateTime(theDateVariable,0) = 5/3/2003 3:47:29 PM 'vbGeneralDate
FormatDateTime(theDateVariable,1) = Wednesday, May 03, 2003 'vbLongDate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;SetLocale(“tr”)&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TypeName(theDateVariable) = Date
IsDate(theDateVariable) = True
FormatDateTime(theDateVariable,0) = 03.05.2003 15:47:29 'vbGeneralDate
FormatDateTime(theDateVariable,1) = 03 Mayis 2003 Çarsamba 'vbLongDate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Ok, so where’s the problem?
&lt;/h2&gt;

&lt;p&gt;Here’s what happens if I do not cast the value using CDate():&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Test #3
&lt;/h3&gt;

&lt;p&gt;I’ll set the variable to the 3rd of May again and this time rely on implicit data-type conversion…then I’ll pass it through the same tests as above and watch it break.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;%
 SetLocale("en-ca")
 dim theDateVariable
 theDateVariable = "03/05/2003 3:47:29 PM"
%&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TypeName(theDateVariable) = String 'Whoa!!!!!!!!!!!
IsDate(theDateVariable) = True
FormatDateTime(theDateVariable,0) = 03/05/2003 3:47:29 PM 'vbGeneralDate
FormatDateTime(theDateVariable,1) = May 3, 2003 'vbLongDate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;SetLocale(“es-es”)&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TypeName(theDateVariable) = String 'Whoa!!!!!!!!!!!
IsDate(theDateVariable) = True
FormatDateTime(theDateVariable,0) = 03/05/2003 15:47:29 'vbGeneralDate
FormatDateTime(theDateVariable,1) = miércoles, 03 de mayo de 2003 'vbLongDate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;SetLocale(“en-us”)&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TypeName(theDateVariable) = String 'Whoa!!!!!!!!!!!
IsDate(theDateVariable) = True
FormatDateTime(theDateVariable,0) = 3/5/2003 3:47:29 PM 'vbGeneralDate
FormatDateTime(theDateVariable,1) = Sunday, March 05, 2003 'Whoa!!!!!!!!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;SetLocale(“tr”)&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TypeName(theDateVariable) = String 'Whoa!!!!!!!!!!!
IsDate(theDateVariable) = True
FormatDateTime(theDateVariable,0) = 03.05.2003 15:47:29 'vbGeneralDate
FormatDateTime(theDateVariable,1) = 03 Mayis 2003 Çarsamba 'vbLongDate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem is obvious I hope:&lt;/p&gt;

&lt;p&gt;The script engine switched the month and day around when the locale was reset to one which isn’t consistent with the original input. Actually…it didn’t switch them around but we hoped it would! Like, why didn’t Microsoft realize that what we meant was the 3rd of May!? – just kidding.&lt;/p&gt;

&lt;p&gt;This of course doesn’t happen if the day is greater than 12 (because the script engine surely knows that there are only 12 months and it will adjust for our laziness for dates like: “30/12/2003” or “12/30/2003”).&lt;/p&gt;

&lt;p&gt;And no exceptions were thrown. The “IsDate()” function and all others worked just fine and the script engine was able to implicitly convert the string value to a date value – but it’s clearly the wrong date!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(Imagine explaining that to your CEO when all transactions posted in the first 12 days of every month are potentially wrong).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To conclude, “yes, a date is always a date” in the VBScript environment. The built-in functions are great and work very well…but only if you know with absolute certainty that your date begins as date and you can predict the Regional Settings and LCID/locale currently in use.&lt;/p&gt;

&lt;p&gt;But you just can’t be certain that every web server running your application will have identical Regional Settings.&lt;/p&gt;

&lt;p&gt;One rule of thumb is demonstrated clearly above: &lt;em&gt;Never trust implicit data-type conversion in the ASP/VBScript environment. Always define the data-type explicitly so that you can rely on a string being a string, a number being a number, and a date being a date.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can see that by casting the variable as a date early in example #2 prevented the problem experienced in #3.&lt;/p&gt;

&lt;h2&gt;
  
  
  But the problem doesn’t stop there…
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What About User Input?
&lt;/h3&gt;

&lt;p&gt;This almost always means that you’ll be receiving data from ASP’s “Request” object: usually either the “Request.form” for “Request.querystring” methods.&lt;/p&gt;

&lt;p&gt;That means two things:&lt;/p&gt;

&lt;p&gt;The incoming data is either “String” data-type or an “IStringList” – but always a string-like thing. Your goal should be to immediately validate, test, and convert the incoming value to a suitable data-type so that later in the code you can trust the type of data you’re dealing with.&lt;/p&gt;

&lt;p&gt;And the incoming data is totally unpredictable! So: validate, test, then immediately convert the incoming value to a suitable data-type.&lt;/p&gt;

&lt;p&gt;If your users are scattered across the globe like mine are, then even the most careful input can be misinterpreted: Is February 1st really 01/02? or 02/01? or 01-02? or 02-01? or 1:2?&lt;/p&gt;

&lt;h3&gt;
  
  
  What About Information From a Database?
&lt;/h3&gt;

&lt;p&gt;This almost always means that you’ll be receiving data from an ADO recordset.&lt;/p&gt;

&lt;p&gt;That means two things:&lt;/p&gt;

&lt;p&gt;The incoming data is a “Field” data-type – it’s neither a number nor string nor date but a “Field”! Your goal should be to immediately convert the incoming value to a suitable data-type so that you can reliably pass the variable around your code without worrying about implicit type conversions.&lt;/p&gt;

&lt;p&gt;And the incoming data is predictable. You’ll be able to trust that ADO is providing you with valid data (usually something you can easily test as NULL, or convert to a string/number/date/currency, etc.)&lt;/p&gt;

&lt;p&gt;But again, if your application is running on systems configured with unpredictable Regional Settings, then your MS Access or MSSQL database may respond with values that your code isn’t prepared for.&lt;/p&gt;

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

&lt;p&gt;I really mean this: &lt;em&gt;avoid using dates whenever possible!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This policy isn’t without problems, but I’d much rather manage numbers than bizarre values like “09-04-01 04.12.00” and have to guess what language or country that relates to or which of those numbers is the month.&lt;/p&gt;

&lt;p&gt;It’s really quite simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;%
 dim dblNow
 dblNow = CDbl(Now())
%&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;VBScript’s date functions will all work as well and better with a “double” rather than with a “date”. As well, the locale or LCID can be changed with liberty and without breaking the date functions when you do need them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is a “Date” really a Double?
&lt;/h3&gt;

&lt;p&gt;Yes. A date can be represented as a “Double” number (that’s a floating-point decimal number).&lt;/p&gt;

&lt;p&gt;The VBScript engine will store, calculate, and display dates using numbers instead of bizarre strings of letters/numbers/weird-characters like “14/1/1997 3:34:00 PM”. In fact, the script engine uses numeric representations already.&lt;/p&gt;

&lt;p&gt;For example, the following numbers can be easily transformed into dates and vice-versa:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FormatDateTime(0,1) = December 30, 1899
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Zero is considered the beginning of time – the VBScript engine assumes that midnight on December 30, 1899 was the beginning of time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CDbl(Now()): 38837.7364467593
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;“Now()” can be represented as a decimal number. The numbers preceding the decimal indicate the number of days since December 30, 1899. The digits following the decimal is a fraction representing the portion of today that has passed (according to the code above, 73.645% of today has passed).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FormatDateTime(38837.7364467593,1) = April 30, 2006
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see that we can plug the decimal number back into the FormatDateTime() function (the function then implicitly converts the data to a date/string).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FormatDateTime(DateAdd(“D”,38837.7364467593,1),1) = May 1, 2006
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see above that the DateAdd() function still enables us to perform math with the “Double”. I’ve added one (1) day (“D”) and the script engine responds as you’d expect with tomorrow’s date. &lt;/p&gt;

&lt;p&gt;All the other built-in functions work too, except that “IsDate()” will prove False.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FormatDateTime((38837.7364467593 + 1),1) = May 1, 2006
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, I can add one (1) to our “Double” number and get the same answer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Test #4
&lt;/h3&gt;

&lt;p&gt;This time, I’ll set the variable to the 3rd of May again and convert the data immediately to a “Double”…everything works except this time the “IsDate()” fails (which I expect because I’ve purposely changed the data-type to “Double”).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;%
 SetLocale("en-ca")
 dim dblDate
 dblDate = CDbl(CDate("03/05/2003 3:47:29 PM"))
%&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TypeName(dblDate) = Double 'THE WAY WE LIKE!!!!!!
IsDate(dblDate) = False 'AS EXPECTED!!!!!!
FormatDateTime(dblDate,0) = 03/05/2003 3:47:29 PM 'vbGeneralDate
FormatDateTime(dblDate,1) = May 3, 2003 'vbLongDate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;SetLocale(“es-es”)&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TypeName(dblDate) = Double 'THE WAY WE LIKE!!!!!!
IsDate(dblDate) = False 'AS EXPECTED!!!!!!
FormatDateTime(dblDate,0) = 03/05/2003 15:47:29 'vbGeneralDate
FormatDateTime(dblDate,1) = miércoles, 03 de mayo de 2003 'vbLongDate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;SetLocale(“en-us”)&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TypeName(dblDate) = Double 'THE WAY WE LIKE!!!!!!
IsDate(dblDate) = False 'AS EXPECTED!!!!!!
FormatDateTime(dblDate,0) = 5/3/2003 3:47:29 PM 'vbGeneralDate
FormatDateTime(dblDate,1) = Wednesday, May 03, 2003 'vbLongDate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;SetLocale(“tr”)&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TypeName(dblDate) = Double 'THE WAY WE LIKE!!!!!!
IsDate(dblDate) = False 'AS EXPECTED!!!!!!
FormatDateTime(dblDate,0) = 03.05.2003 15:47:29 'vbGeneralDate
FormatDateTime(dblDate,1) = 03 Mayis 2003 Çarsamba 'vbLongDate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wednesday, May 3rd in every locale!&lt;/p&gt;

&lt;h2&gt;
  
  
  What About User Input?
&lt;/h2&gt;

&lt;p&gt;If you forge ahead with my solution, you’ll still find that this is the most difficult aspect of an application. Users just aren’t as predictable as we’d like.&lt;/p&gt;

&lt;p&gt;Immediately validate, test, and convert the user’s input to a “Double” when you retrieve the information from “Request.form” or “Request.querystring”. I use a function for this purpose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;%
 dim dblDate
 dblDate = DblDate(request.form("TodaysDate"))

 FUNCTION DblDate(ByVal variantDate)
 ' the argument might be any of the following data types:
 ' Date (if a valid date is coming from a database or elsewhere in the application)
 ' Double (if the variable has already been converted to a double)
 ' IStringList (if data such as "123456,123456789" is coming from elsewhere in the application)
 ' Field (in which case it likely contains a double or a string formatted like a double or an IStringList by the database)
 ' String like "10/10/2003 12:00:00 AM"

 dim dblDateValue
 dim dblTimeValue

 on error resume next

 IF (TypeName(variantDate) = "Date") OR (TypeName(variantDate) = "IStringList") THEN
 'Then it's a date and the CDbl conversion will work
 dblDateValue = CDbl(Replace(variantDate,",","."))

 ELSEIF TypeName(variantDate) = "Double" THEN
 'Then it's already a double...no conversion necessary
 dblDateValue = variantDate

 ELSE
 'Then it's either a field or a string and things get tricky
 dblDateValue = CDbl(CDate(variantDate))

  IF err.Number 0 THEN
  'If the logic above caused an error, then the CDate() conversion wasn't successful.
  'which means that the incoming value isn't a known date format - maybe it's a number
  'or maybe it's a string-type date in a different locale or language
  'or maybe it's a recipe for eggs benedict...let's try one last time:
  err.Clear
  dblDateValue = CDbl(variantDate)
  END IF

 END IF

 IF err.Number &amp;lt;&amp;gt; 0 THEN
 'if there's still an error, then the incoming value cannot be interpreted as a date or number
 'we can't say we didn't try...but so to not break the rest of the code we'll assign a value of zero
 'and return a valid "Double" anyways!
 dblDateValue = CDbl(0)
 END IF

 err.Clear
 on error GoTo 0

 'and now we can return a valid double
 DblDate = dblDateValue

 END FUNCTION
%&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And after the user’s input is successfully validated and converted to a “Double”, you can pass that variable around in your code. You can perform math with it, display it on your page, dump it into a database, etc. and because it’s a number, not a date, changing the locale or LCID won’t have any unexpected results.&lt;/p&gt;

&lt;p&gt;Well, I’m glad that’s settled!&lt;/p&gt;

&lt;h2&gt;
  
  
  But what’s the “IStringList” exactly?
&lt;/h2&gt;

&lt;p&gt;The only problem I have encountered using “Double” instead of “Date” data types is that VBScript will format a “Double” with a comma instead of a period – and the reason isn’t obvious.&lt;/p&gt;

&lt;p&gt;The following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;%
 SetLocale("en-ca")
 response.write(CDbl(1234.5678))
 response.write("&amp;lt;br /&amp;gt;")

 SetLocale("es-es")
 response.write(CDbl(1234.5678))
 response.write("&amp;lt;br /&amp;gt;")
%&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Will output this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1234.5678
1234.5678
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But…this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;%
 SetLocale("en-ca")
 response.write(CDbl(1234.5678) &amp;amp;"&amp;lt;br /&amp;gt;")

 SetLocale("es-es")
 response.write(CDbl(1234.5678) &amp;amp;"&amp;lt;br /&amp;gt;")
%&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;…which you’d think is fundamentally the same, will output this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1234.5678
1234,5678 'Note the comma!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, what’s different between the first and second examples?&lt;/p&gt;

&lt;p&gt;In the first example above, the number was converted to a double, then passed to the “Response” object which implicitly converted the data to a “String” when the ASP engine wrote to the output buffer.&lt;/p&gt;

&lt;p&gt;In the second example, the number was converted to a double, then immediately/implicitly to a string by the VBScript engine when we concatenated the tag!&lt;/p&gt;

&lt;p&gt;What can we learn by this?&lt;/p&gt;

&lt;p&gt;We can learn that the “Response” object is a perfectly dumb object – it just throws everything it recieves to the output buffer – with “ToString” character conversion. We can also learn that VBScript formats a “Double” with a comma in the “Español (España)” locale. When in Spain, if we try to convert from a string to a double, then we have to expect that the incoming data-type might be an “IStringList”: a comma-separated list as in “1234 , 5678”. This will occur if you retrieve the value from the “request.querystring” or “request.form” methods.&lt;/p&gt;

&lt;p&gt;Assume for a moment that a querystring key named “spanishDouble” has a value of “1234,5678” as in: &lt;code&gt;thisPage.asp?spanishDouble=1234,5678&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;&amp;lt;%
 SetLocale("es-es")

 ' This will be "IStringList"
 response.write(TypeName(request.querystring("spanishDouble")))
 response.write("&amp;lt;br /&amp;gt;")

 dim varSpanishDouble
 ' But it will be implicitly cast as a "String" here.
 varSpanishDouble = request.querystring("spanishDouble")

 ' Proof!
 response.write(TypeName(varSpanishDouble))
 response.write("&amp;lt;br /&amp;gt;")

 ' And, the CDbl() function works.
 response.write(FormatDateTime(CDbl(varSpanishDouble),1))
 response.write("&amp;lt;br /&amp;gt;")
%&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Will output this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IStringList
Empty
sábado, 30 de diciembre de 1899
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hmm…&lt;/p&gt;

&lt;p&gt;Now let’s throw the querystring immediately into the CDbl() without assigning it first to a variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;%
 SetLocale("es-es")

 ' This will be "IStringList"
 response.write(TypeName(request.querystring("spanishDouble")))
 response.write("&amp;lt;br /&amp;gt;")

 response.write(FormatDateTime(CDbl(request.querystring("spanishDouble")),1))
 response.write("&amp;lt;br /&amp;gt;")
%&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Will output this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IStringList
sábado, 30 de diciembre de 1899
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now to stir things up…if the incoming querystring value (in the Spanish example) has a period instead of a comma, then the “CDbl()” will strip the period entirely (instead of as you’d hope it should convert the period to a comma) and the conversion will be incorrect.&lt;/p&gt;

&lt;p&gt;So, the number “1234.5678” becomes “12345678” and an error occurs because that’s not a valid date (that’s 33 thousand years past December 30, 1899).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So the rule is: “Double” data-types in some locales will be formatted with a comma, not with a decimal-period.&lt;/strong&gt; Once you understand that single exception, then using “Double” types is a lot easier than using “Date” types. Using “Date” types immediately introduces as many exceptions as there are rules!&lt;/p&gt;

&lt;h2&gt;
  
  
  What about Information From a Database?
&lt;/h2&gt;

&lt;p&gt;Imagine now that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;your ASP pages are running on a web server in France, but your SQL database is on a server in España.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;or, (perhaps more commonly), perhaps you use a MS Access database on the same computer or network as your web server but your ASP scripts use a LCID that differs from the system’s Regional Settings.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both of these scenarios are common, and both pose the same problem: the database is liable to receive and respond with data that is formatted differently than your script engine. I can think of a few thousands ways that otherwise great code can break…they all boil down to data-type mismatch or syntax errors in your UPDATE or INSERT queries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enter the “Double”!
&lt;/h3&gt;

&lt;p&gt;I store dates as dates in a database – I mean, why not? But that’s as far as it goes…as I retrieve information from a database I convert it to a “Double” and the data stays that way until I output it to a page with the FormatDateTime() function (whereby it gets implicitly converted to a string) or until I purposely convert it to a field or string to put back into the database! Consider the following:&lt;/p&gt;

&lt;p&gt;To retrieve data from a database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'MS Access
set objRecordsetObject = objConnectionObject.Execute("SELECT CDbl(datefield) AS dblDateField FROM table;")

'SQL
set objRecordsetObject = objConnectionObject.Execute("SELECT convert(float,datefield)+2 AS dblDateField FROM table;")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note, the “+2” is to accommodate the fact that MSSQL considers January, 1, 1900 to be the beginning of time (zero) while VBScript considers December 30, 1899 to be beginning of time (zero). I know, I know…you’re thinking “that’s dumb!”&lt;/p&gt;

&lt;p&gt;These example queries are important for two reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;First, the database will perform the conversion from date to double. That’s great considering the alternative. If we instead retreive a “date” from the database and ask the VBScript engine to perform the conversion then we run the risk that the two environments may interpret the values differently. But we can be assured that the database will produce a double/float that is exactly equal to the date every time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Secondly, because there’s no mystery at all about what the value might look like when VBScript gets its hands on it. We know that it will a floating-point decimal-digit number; it won’t be NULL! and it won’t be a bizarre string of alpha-numeric-babble.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We can immediately do this and life is good:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dim dblDate
dblDate = CDbl(objRecordsetObject("dblDateField"))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, because we have a value that we know and trust is a valid “Double”, we can manipulate it, compare and test it, and write it out to a page – do whatever you want with it. You’ll find yourself as comfortable using these variables as you are with integers and text.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example…
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IF dblDate = 0 THEN
 response.write("It's the beginning of time!&amp;lt;br /&amp;gt;")
ELSE
 SetLocale("es-es")
 response.write("The date in Spanish is: "&amp;amp; FormatDateTime(dblDate,1) &amp;amp;"&amp;lt;br /&amp;gt;")
 SetLocale("fr-ca")
 response.write("The date in Canada is: "&amp;amp; FormatDateTime(dblDate,1) &amp;amp;"&amp;lt;br /&amp;gt;")
 response.write("The next day is "&amp;amp; MonthName(dblDate+1) &amp;amp;", "&amp;amp; Year(dblDate+1) &amp;amp;"&amp;lt;br /&amp;gt;")
 SetLocale("tr")
 response.write("A month earlier in Turkey: "&amp;amp; FormatDateTime(DateAdd("M",dblDate,-1)) &amp;amp;"&amp;lt;br /&amp;gt;")
END IF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  And Updating or Inserting into a Database
&lt;/h3&gt;

&lt;p&gt;Again, when passing a “double” to a database, it’s best to let the database perform the number-to-date conversion because it doesn’t get confused. The various tools, ASP, VBScript, and your data provider get confused with dates because they each interpret dates according to their own unique rules – but they never confuse numbers.&lt;/p&gt;

&lt;p&gt;In the example below assume that the “datefield” is a database column of type “date” (date/time or smalldate, whatever you happen to be using.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'MS Access
objConnectionObject.Execute("INSERT INTO table (datefield) VALUES ("&amp;amp; Replace(dblDate,",",".") &amp;amp;");")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, if this string were written with constants, then it might look 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;“INSERT INTO table (datefield) VALUES (1234.5678);”
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you’ll say, “but doesn’t that cause a type mismatch?”. Nope. It doesn’t.&lt;/p&gt;

&lt;p&gt;And note that the VBScript “Replace()” function can be used for good measure to ensure that those Spanish doubles (with commas) won’t cause a syntax error in the query.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Make it a “Double”.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>vbscript</category>
      <category>asp</category>
      <category>programming</category>
    </item>
    <item>
      <title>Docker Compose, Hello World</title>
      <dc:creator>David Sabine</dc:creator>
      <pubDate>Fri, 25 Nov 2022 19:22:14 +0000</pubDate>
      <link>https://dev.to/davidsabine/docker-compose-hello-world-1p14</link>
      <guid>https://dev.to/davidsabine/docker-compose-hello-world-1p14</guid>
      <description>&lt;h2&gt;
  
  
  Let’s use docker-compose to create containers.
&lt;/h2&gt;

&lt;p&gt;In my &lt;a href="https://dev.to/davidsabine/docker-hello-world-3093"&gt;previous post&lt;/a&gt;, we used the publicly available &lt;code&gt;hello world&lt;/code&gt; image to create Docker containers.&lt;/p&gt;

&lt;p&gt;Now, let’s use &lt;code&gt;docker-compose&lt;/code&gt; to do the exact same thing.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Make a new folder on your drive somewhere. Call it anything you want.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Inside that new folder, create ONE file (for now) with the following name:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
└── docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Write these lines into the new &lt;code&gt;docker-compose.yml&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;hello_world&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hello-world&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run the command: &lt;code&gt;docker-compose up&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Docker will compose a new “compose project” (that’s what they call it) and, inside it, a new container is created using the publicly available &lt;code&gt;hello-world&lt;/code&gt; image.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;And note the name of the new container will be {your folder name}-{the image name}-{a number}. &lt;code&gt;docker container ls -a&lt;/code&gt; to see list all your containers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Important note, the &lt;a href="https://docs.docker.com/desktop/" rel="noopener noreferrer"&gt;Docker Desktop GUI&lt;/a&gt;, will show:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a compose project named {your foldername}&lt;/li&gt;
&lt;li&gt;a container (as a child of the compose project) named {the image name}-{a number}&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;And try running the command again: &lt;code&gt;docker-compose up&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Unlike &lt;a href="https://dev.to/davidsabine/docker-hello-world-3093"&gt;the previous post&lt;/a&gt;, wherein a new container is produced each time you run &lt;code&gt;docker run hello-world&lt;/code&gt;, a new container is &lt;strong&gt;not&lt;/strong&gt; produced by &lt;code&gt;docker-compose up&lt;/code&gt;; rather, Docker will attach to the existing container inside the “compose project” made in the previous and will run the command in the &lt;code&gt;hello-world&lt;/code&gt; image.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Now, let’s do the same thing, but this time we’ll add Dockerfile.
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why would we want a Dockerfile? Why not do it all in &lt;code&gt;docker-compose.yml&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image. (I stole that sentence from &lt;a href="https://docs.docker.com/engine/reference/builder/" rel="noopener noreferrer"&gt;Docker Docs&lt;/a&gt;.) Imagine &lt;strong&gt;a single computer&lt;/strong&gt; that you can copy and reuse.&lt;/p&gt;

&lt;p&gt;And a &lt;code&gt;docker-compose.yml&lt;/code&gt; file lets us compose applications that use multiple containers. Imagine &lt;strong&gt;a network of computers&lt;/strong&gt; that you can copy and reuse.&lt;/p&gt;

&lt;h3&gt;
  
  
  Your Turn
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;In the folder you made in #1 above, create another file called “Dockerfile”:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
├── docker-compose.yml
└── Dockerfile
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In your new &lt;code&gt;Dockerfile&lt;/code&gt;, add the following:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;FROM hello-world&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;That line will tell Docker to build an image from the publicy available &lt;code&gt;hello-world&lt;/code&gt; image. (The same image used in #3 above.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now, we can tell docker-compose to use the new Dockerfile, as follows:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;hello-world&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Interesting to note: docker will name the new artifacts exactly as in the previous step: {the folder name}-{the image name}-{a number}. But, we actually have some control of these details. Carry on…&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Modify your docker-compose as follows:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;my-awesome-app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run &lt;code&gt;docker-compose up&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Note the name of the new container is {the folder name}-&lt;strong&gt;my-awesome-app&lt;/strong&gt;-{a number}.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now, to understand the power of &lt;code&gt;docker-compose&lt;/code&gt;, modify your file as follows:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;my-awesome-app-1&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
  &lt;span class="na"&gt;my-awesome-app-2&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run &lt;code&gt;docker-compose up&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now, when you run &lt;code&gt;docker-container ls -a&lt;/code&gt;, you’ll see &lt;strong&gt;two&lt;/strong&gt; containers were created with the names:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;{the folder name}-&lt;strong&gt;my-awesome-app-1&lt;/strong&gt;-{a number}&lt;/li&gt;
&lt;li&gt;{the folder name}-&lt;strong&gt;my-awesome-app-2&lt;/strong&gt;-{a number}&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And both used the same &lt;code&gt;hello-world&lt;/code&gt; image configured in &lt;code&gt;Dockerfile&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Using &lt;code&gt;docker-compose&lt;/code&gt;, you downloaded an image, created containers from that image, and ran a program on that image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Incorporating &lt;code&gt;Dockerfile&lt;/code&gt;, you separated the concerns nicely: one file that describes a reusable computer; another file that describes a network of computers.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>github</category>
      <category>news</category>
    </item>
    <item>
      <title>Docker, Hello World</title>
      <dc:creator>David Sabine</dc:creator>
      <pubDate>Fri, 25 Nov 2022 19:17:48 +0000</pubDate>
      <link>https://dev.to/davidsabine/docker-hello-world-3093</link>
      <guid>https://dev.to/davidsabine/docker-hello-world-3093</guid>
      <description>&lt;p&gt;If you’ve never used Docker before, this is where to start.&lt;/p&gt;

&lt;p&gt;Let’s say “Hello World!” in a Docker container.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-requisites: Ensure Docker is Installed &amp;amp; Working
&lt;/h2&gt;

&lt;p&gt;It’s important you have Docker Engine and Docker CLI and Docker Compose. How to know if you have these on your system?&lt;/p&gt;

&lt;p&gt;Note: &lt;a href="https://docs.docker.com/compose/install/"&gt;Docker Desktop&lt;/a&gt; for Linux/Mac/Windows includes all the necessary tools.&lt;/p&gt;

&lt;p&gt;You’ll know whether these tools are installed and working if, at any command prompt, the following commands will report the version number of each tool.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nt"&gt;--version&lt;/span&gt;

My system responds with:
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Docker version 20.10.17, build 100c701
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose &lt;span class="nt"&gt;--version&lt;/span&gt;

My system responds with:
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;Docker Compose version v2.10.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Let’s make some containers from an existing image, then remove them from our system.
&lt;/h2&gt;

&lt;p&gt;It’s helpful to know a few basics to keep your environment clean.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;docker pull hello-world&lt;/code&gt;: Build a simple image in a docker container and run a “Hello World” application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;docker images&lt;/code&gt;: List all your images. You’ll see a new image, called &lt;code&gt;hello-world&lt;/code&gt; is added to your local collection.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;docker run hello-world&lt;/code&gt;: Run the app within the container.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;docker container ls -a&lt;/code&gt;: List all docker containers.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It’s important to know that a new container is produced every time you run the app. For example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Run #3 above, again.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then run #4 above, again, and notice a new container in the list.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;(To prevent the creation of a new container every time you want to interact with the app, there are ways to execute commands in a running container, &lt;em&gt;et cetera&lt;/em&gt;. Those techniques are not described here.)&lt;/p&gt;

&lt;p&gt;It's important to know how to clean up your environment.&lt;/p&gt;

&lt;p&gt;(These commands &lt;strong&gt;and more&lt;/strong&gt; are described in the &lt;a href="https://linuxhandbook.com/remove-docker-images/"&gt;“Complete Guide for Removing Docker Images” by Abhishek Prakash&lt;/a&gt;.)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;docker container ls -a&lt;/code&gt;: List all your containers. (Note the names or container ids.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;docker rm boring_hoover&lt;/code&gt;: Remove a container with name “boring_hoover”.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;docker image rm hello-world&lt;/code&gt;: This will remove the hello-world image created in #1 above. Note this will fail if any containers exist using that image. (So remove those images first.)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Using &lt;code&gt;docker&lt;/code&gt;, you downloaded an image, created containers from that image, and ran a program on that image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then you cleaned up the Docker artifacts on your system: the containers and the new image.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  See also
&lt;/h2&gt;

&lt;p&gt;My &lt;a href="https://dev.to/davidsabine/docker-compose-hello-world-1p14"&gt;next article&lt;/a&gt; demonstrates how to do all this with &lt;code&gt;docker-compose&lt;/code&gt;.&lt;/p&gt;

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