{"data":{"post":{"fields":{"slug":"/minio-as-s3-replacement-in-development-and-beyond/","date":"2018-06-04"},"html":"<ul>\n<li><a href=\"#what-is-minio\">What is Minio</a></li>\n<li><a href=\"#how-to-spin-it-up\">How to spin it up</a></li>\n<li><a href=\"#minio-browser\">Minio Browser</a></li>\n<li><a href=\"#integration-with-php-sdk\">Integration with PHP SDK</a></li>\n<li><a href=\"#integration-with-flysystem\">Integration with Flysystem</a></li>\n</ul>\n<h2><a name=\"what-is-minio\"></a>What is Minio?</h2>\n<p><a href=\"https://minio.io\">Minio</a> is open source AWS S3 compatible file storage.\nYou can run it on environment you fully control.</p>\n<p>This blog post assumes you use Minio for development / testing purposes as AWS S3 replacement.</p>\n<p>If you are interested in production usage then you should take a look at <a href=\"https://docs.minio.io/docs/distributed-minio-quickstart-guide\">distributed Minio</a> mode which contains data loss protection features.</p>\n<h2><a name=\"how-to-spin-it-up\"></a>How to spin it up?</h2>\n<p>Fastest way is to use Docker.\nSingle instance can be created using following <code class=\"language-text\">docker-compose.yml</code> container definition:</p>\n<div class=\"gatsby-highlight\" data-language=\"yaml\"><pre class=\"language-yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">minio</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">image</span><span class=\"token punctuation\">:</span> minio/minio<span class=\"token punctuation\">:</span>RELEASE.2018<span class=\"token punctuation\">-</span>05<span class=\"token punctuation\">-</span>16T23<span class=\"token punctuation\">-</span>35<span class=\"token punctuation\">-</span>33Z\n    <span class=\"token key atrule\">volumes</span><span class=\"token punctuation\">:</span>\n        <span class=\"token comment\"># adjust volume to your needs</span>\n        <span class=\"token punctuation\">-</span> <span class=\"token string\">\"../.data/minio:/data\"</span>\n    <span class=\"token key atrule\">ports</span><span class=\"token punctuation\">:</span>\n        <span class=\"token punctuation\">-</span> $<span class=\"token punctuation\">{</span>MINIO_PORT<span class=\"token punctuation\">}</span><span class=\"token punctuation\">:</span><span class=\"token number\">9000</span>\n    <span class=\"token key atrule\">environment</span><span class=\"token punctuation\">:</span>\n        <span class=\"token key atrule\">MINIO_ACCESS_KEY</span><span class=\"token punctuation\">:</span> $<span class=\"token punctuation\">{</span>S3_KEY<span class=\"token punctuation\">}</span>\n        <span class=\"token key atrule\">MINIO_SECRET_KEY</span><span class=\"token punctuation\">:</span> $<span class=\"token punctuation\">{</span>S3_SECRET<span class=\"token punctuation\">}</span>\n    <span class=\"token key atrule\">command</span><span class=\"token punctuation\">:</span> server /data\n    <span class=\"token key atrule\">restart</span><span class=\"token punctuation\">:</span> unless<span class=\"token punctuation\">-</span>stopped</code></pre></div>\n<p>The tricky part is bucket configuration.\nThere is <code class=\"language-text\">mc</code> CLI client to configure Minio.\nIn order to automate everything you can configure buckets using another docker container:</p>\n<div class=\"gatsby-highlight\" data-language=\"yaml\"><pre class=\"language-yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">createbuckets</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">image</span><span class=\"token punctuation\">:</span> minio/mc<span class=\"token punctuation\">:</span>RELEASE.2018<span class=\"token punctuation\">-</span>04<span class=\"token punctuation\">-</span>28T00<span class=\"token punctuation\">-</span>08<span class=\"token punctuation\">-</span>20Z\n    <span class=\"token key atrule\">depends_on</span><span class=\"token punctuation\">:</span>\n        <span class=\"token punctuation\">-</span> minio\n    <span class=\"token key atrule\">entrypoint</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">></span><span class=\"token scalar string\">\n        /bin/sh -c \"\n        /usr/bin/mc config host add minio http://minio:9000 ${S3_KEY} ${S3_SECRET};</span>\n\n        /usr/bin/mc mb minio/bucket_with_no_public_access;\n        /usr/bin/mc policy none minio/bucket_with_no_public_access;\n\n        /usr/bin/mc mb minio/bucket_with_public_download;\n        /usr/bin/mc policy download minio/bucket_with_public_download;\n\n        exit 0;\n        \"</code></pre></div>\n<p>It will exit as soon as job is done. It’s perfectly OK ;-)</p>\n<h2><a name=\"minio-browser\"></a>Minio Browser</h2>\n<p>Assuming your <code class=\"language-text\">MINIO_PORT</code> defined in <code class=\"language-text\">.env</code> is <code class=\"language-text\">9001</code> you can just go to <code class=\"language-text\">http://localhost:9001</code> using browser.\nEnter <code class=\"language-text\">S3_KEY</code> and <code class=\"language-text\">S3_SECRET</code> values and you should see Minio dashboard.</p>\n<h2><a name=\"integration-with-php-sdk\"></a>Integration with PHP SDK</h2>\n<p>Ensure <code class=\"language-text\">aws/aws-sdk-php</code> is present in your <code class=\"language-text\">composer.json</code>.</p>\n<div class=\"gatsby-highlight\" data-language=\"php\"><pre class=\"language-php\"><code class=\"language-php\"><span class=\"token variable\">$client</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\"><span class=\"token punctuation\">\\</span>Aws<span class=\"token punctuation\">\\</span>S3<span class=\"token punctuation\">\\</span>S3Client</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span>\n    <span class=\"token single-quoted-string string\">'version'</span> <span class=\"token operator\">=</span><span class=\"token operator\">></span> <span class=\"token single-quoted-string string\">'2006-03-01'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token single-quoted-string string\">'region'</span> <span class=\"token operator\">=</span><span class=\"token operator\">></span> <span class=\"token single-quoted-string string\">'eu-central-1'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token single-quoted-string string\">'endpoint'</span> <span class=\"token operator\">=</span><span class=\"token operator\">></span> <span class=\"token single-quoted-string string\">'http://minio:9000'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token single-quoted-string string\">'use_path_style_endpoint'</span> <span class=\"token operator\">=</span><span class=\"token operator\">></span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// this is super important</span>\n    <span class=\"token single-quoted-string string\">'credentials'</span> <span class=\"token operator\">=</span><span class=\"token operator\">></span> <span class=\"token punctuation\">[</span>\n        <span class=\"token single-quoted-string string\">'key'</span> <span class=\"token operator\">=</span><span class=\"token operator\">></span> <span class=\"token single-quoted-string string\">'s3key'</span><span class=\"token punctuation\">,</span>\n        <span class=\"token single-quoted-string string\">'secret'</span> <span class=\"token operator\">=</span><span class=\"token operator\">></span> <span class=\"token single-quoted-string string\">'s3secret'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">]</span>\n<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<h2><a name=\"integration-with-flysystem\"></a>Integration with Flysystem on Symfony</h2>\n<p>Ensure you have following dependencies in your <code class=\"language-text\">composer.json</code>:</p>\n<ul>\n<li><code class=\"language-text\">oneup/flysystem-bundle</code></li>\n<li><code class=\"language-text\">league/flysystem-aws-s3-v3</code></li>\n</ul>\n<p>Define S3Client service in <code class=\"language-text\">config/services.yaml</code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"yaml\"><pre class=\"language-yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">parameters</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">app.s3_client.version</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'%env(S3_VERSION)%'</span>\n    <span class=\"token key atrule\">app.s3_client.region</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'%env(S3_REGION)%'</span>\n    <span class=\"token key atrule\">app.s3_client.endpoint</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'http://minio:9000'</span>\n    <span class=\"token key atrule\">app.s3_client.key</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'%env(S3_KEY)%'</span>\n    <span class=\"token key atrule\">app.s3_client.secret</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'%env(S3_SECRET)%'</span>\n\n<span class=\"token key atrule\">app.s3_client</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">class</span><span class=\"token punctuation\">:</span> Aws\\S3\\S3Client\n        <span class=\"token key atrule\">arguments</span><span class=\"token punctuation\">:</span>\n            <span class=\"token punctuation\">-</span>\n                <span class=\"token key atrule\">version</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'%app.s3_client.version%'</span>\n                <span class=\"token key atrule\">region</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'%app.s3_client.region%'</span>\n                <span class=\"token key atrule\">endpoint</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'%app.s3_client.endpoint%'</span>\n                <span class=\"token key atrule\">use_path_style_endpoint</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n                <span class=\"token key atrule\">credentials</span><span class=\"token punctuation\">:</span>\n                    <span class=\"token key atrule\">key</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'%app.s3_client.key%'</span>\n                    <span class=\"token key atrule\">secret</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'%app.s3_client.secret%'</span></code></pre></div>\n<p>Define filesystems in <code class=\"language-text\">config/packages/oneup_flysystem.yaml</code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"yaml\"><pre class=\"language-yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">oneup_flysystem</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">adapters</span><span class=\"token punctuation\">:</span>\n        <span class=\"token key atrule\">bucket_with_no_public_access</span><span class=\"token punctuation\">:</span>\n            <span class=\"token key atrule\">awss3v3</span><span class=\"token punctuation\">:</span>\n                <span class=\"token key atrule\">client</span><span class=\"token punctuation\">:</span> app.s3_client\n                <span class=\"token key atrule\">bucket</span><span class=\"token punctuation\">:</span> bucket_with_no_public_access\n                <span class=\"token key atrule\">options</span><span class=\"token punctuation\">:</span>\n                    <span class=\"token key atrule\">visibility</span><span class=\"token punctuation\">:</span> private\n                    <span class=\"token key atrule\">ACL</span><span class=\"token punctuation\">:</span> private\n        <span class=\"token key atrule\">bucket_with_public_download</span><span class=\"token punctuation\">:</span>\n            <span class=\"token key atrule\">awss3v3</span><span class=\"token punctuation\">:</span>\n                <span class=\"token key atrule\">client</span><span class=\"token punctuation\">:</span> app.s3_client\n                <span class=\"token key atrule\">bucket</span><span class=\"token punctuation\">:</span> bucket_with_public_download\n                <span class=\"token key atrule\">options</span><span class=\"token punctuation\">:</span>\n                    <span class=\"token key atrule\">visibility</span><span class=\"token punctuation\">:</span> public\n                    <span class=\"token key atrule\">ACL</span><span class=\"token punctuation\">:</span> public\n    <span class=\"token key atrule\">filesystems</span><span class=\"token punctuation\">:</span>\n        <span class=\"token key atrule\">bucket_with_no_public_access</span><span class=\"token punctuation\">:</span>\n            <span class=\"token key atrule\">adapter</span><span class=\"token punctuation\">:</span> bucket_with_no_public_access\n            <span class=\"token key atrule\">alias</span><span class=\"token punctuation\">:</span> bucket_with_no_public_access\n        <span class=\"token key atrule\">bucket_with_public_download</span><span class=\"token punctuation\">:</span>\n            <span class=\"token key atrule\">adapter</span><span class=\"token punctuation\">:</span> bucket_with_public_download\n            <span class=\"token key atrule\">alias</span><span class=\"token punctuation\">:</span> bucket_with_public_download</code></pre></div>\n<p>From now on you can just inject filesystems using newly created <code class=\"language-text\">oneup_flysystem.bucket_with_no_public_access_filesystem</code> and <code class=\"language-text\">oneup_flysystem.bucket_with_public_download_filesystem</code> services.</p>","frontmatter":{"title":"Minio as S3 replacement in development and beyond","subTitle":"How to configure self-hosted S3 file storage with Docker and setup Symfony Flysystem","postAuthor":"Dawid Śpiechowicz","cover":"/img/minio.png"}},"tags":{"group":[{"name":"$OSTYPE","totalCount":1,"edges":[{"node":{"fields":{"slug":"/cross-system-xdebug-docker-compose-setup/"}}}]},{"name":".env","totalCount":1,"edges":[{"node":{"fields":{"slug":"/cross-system-xdebug-docker-compose-setup/"}}}]},{"name":".nvrmc","totalCount":1,"edges":[{"node":{"fields":{"slug":"/travis-problematic-python-and-node/"}}}]},{"name":"AUTO_INCREMENT","totalCount":1,"edges":[{"node":{"fields":{"slug":"/is-mysql-autoincrement-really-monotonic/"}}}]},{"name":"Angular","totalCount":1,"edges":[{"node":{"fields":{"slug":"/Dev-and-prod-ready-Docker-setup-for-SPA-app/"}}}]},{"name":"Command","totalCount":1,"edges":[{"node":{"fields":{"slug":"/complex-command-handler-in-javascript/"}}}]},{"name":"DQL","totalCount":2,"edges":[{"node":{"fields":{"slug":"/doctrine-new-dql-operator-and-objects/"}}},{"node":{"fields":{"slug":"/mysql-decimal-format/"}}}]},{"name":"Data Transfer Object","totalCount":1,"edges":[{"node":{"fields":{"slug":"/doctrine-new-dql-operator-and-objects/"}}}]},{"name":"Docker","totalCount":3,"edges":[{"node":{"fields":{"slug":"/cross-system-xdebug-docker-compose-setup/"}}},{"node":{"fields":{"slug":"/quick-import-of-mysql-database-dump/"}}},{"node":{"fields":{"slug":"/Dev-and-prod-ready-Docker-setup-for-SPA-app/"}}}]},{"name":"Docker Compose","totalCount":3,"edges":[{"node":{"fields":{"slug":"/cross-system-xdebug-docker-compose-setup/"}}},{"node":{"fields":{"slug":"/quick-import-of-mysql-database-dump/"}}},{"node":{"fields":{"slug":"/Dev-and-prod-ready-Docker-setup-for-SPA-app/"}}}]},{"name":"Doctrine","totalCount":2,"edges":[{"node":{"fields":{"slug":"/doctrine-new-dql-operator-and-objects/"}}},{"node":{"fields":{"slug":"/mysql-decimal-format/"}}}]},{"name":"Doctrine NEW","totalCount":1,"edges":[{"node":{"fields":{"slug":"/doctrine-new-dql-operator-and-objects/"}}}]},{"name":"ES7","totalCount":1,"edges":[{"node":{"fields":{"slug":"/async-await-with-express/"}}}]},{"name":"Elastica","totalCount":1,"edges":[{"node":{"fields":{"slug":"/elasticsearch-script-unknown-field-source-parser-not-found/"}}}]},{"name":"Elasticsearch","totalCount":1,"edges":[{"node":{"fields":{"slug":"/elasticsearch-script-unknown-field-source-parser-not-found/"}}}]},{"name":"Elasticsearch script","totalCount":1,"edges":[{"node":{"fields":{"slug":"/elasticsearch-script-unknown-field-source-parser-not-found/"}}}]},{"name":"Express","totalCount":1,"edges":[{"node":{"fields":{"slug":"/async-await-with-express/"}}}]},{"name":"Git","totalCount":2,"edges":[{"node":{"fields":{"slug":"/git-not-detecting-renames-quick-workarounds/"}}},{"node":{"fields":{"slug":"/git-reverting-branch-removal/"}}}]},{"name":"Git renamed","totalCount":1,"edges":[{"node":{"fields":{"slug":"/git-not-detecting-renames-quick-workarounds/"}}}]},{"name":"HTTP","totalCount":1,"edges":[{"node":{"fields":{"slug":"/how-does-slack-communicate-with-spotify/"}}}]},{"name":"JavaScript","totalCount":3,"edges":[{"node":{"fields":{"slug":"/async-await-with-express/"}}},{"node":{"fields":{"slug":"/complex-command-handler-in-javascript/"}}},{"node":{"fields":{"slug":"/how-to-implement-redux-in-react/"}}}]},{"name":"Kafka","totalCount":1,"edges":[{"node":{"fields":{"slug":"/is-mysql-autoincrement-really-monotonic/"}}}]},{"name":"MySQL","totalCount":4,"edges":[{"node":{"fields":{"slug":"/mysql-decimal-format/"}}},{"node":{"fields":{"slug":"/is-mysql-autoincrement-really-monotonic/"}}},{"node":{"fields":{"slug":"/php-with-mysql-8/"}}},{"node":{"fields":{"slug":"/quick-import-of-mysql-database-dump/"}}}]},{"name":"MySQL 8","totalCount":1,"edges":[{"node":{"fields":{"slug":"/php-with-mysql-8/"}}}]},{"name":"Node.js","totalCount":1,"edges":[{"node":{"fields":{"slug":"/travis-problematic-python-and-node/"}}}]},{"name":"ORM","totalCount":1,"edges":[{"node":{"fields":{"slug":"/doctrine-new-dql-operator-and-objects/"}}}]},{"name":"PDO","totalCount":1,"edges":[{"node":{"fields":{"slug":"/php-with-mysql-8/"}}}]},{"name":"PDO_MYSQL","totalCount":1,"edges":[{"node":{"fields":{"slug":"/php-with-mysql-8/"}}}]},{"name":"PHP","totalCount":6,"edges":[{"node":{"fields":{"slug":"/doctrine-new-dql-operator-and-objects/"}}},{"node":{"fields":{"slug":"/mysql-decimal-format/"}}},{"node":{"fields":{"slug":"/cross-system-xdebug-docker-compose-setup/"}}},{"node":{"fields":{"slug":"/php-with-mysql-8/"}}},{"node":{"fields":{"slug":"/elasticsearch-script-unknown-field-source-parser-not-found/"}}},{"node":{"fields":{"slug":"/how-to-write-a-phing-target-autocomplete-bash-script/"}}}]},{"name":"Phing","totalCount":1,"edges":[{"node":{"fields":{"slug":"/how-to-write-a-phing-target-autocomplete-bash-script/"}}}]},{"name":"Promise","totalCount":1,"edges":[{"node":{"fields":{"slug":"/complex-command-handler-in-javascript/"}}}]},{"name":"Python","totalCount":1,"edges":[{"node":{"fields":{"slug":"/travis-problematic-python-and-node/"}}}]},{"name":"React","totalCount":2,"edges":[{"node":{"fields":{"slug":"/how-to-implement-redux-in-react/"}}},{"node":{"fields":{"slug":"/Dev-and-prod-ready-Docker-setup-for-SPA-app/"}}}]},{"name":"Redux","totalCount":1,"edges":[{"node":{"fields":{"slug":"/how-to-implement-redux-in-react/"}}}]},{"name":"Redux store","totalCount":1,"edges":[{"node":{"fields":{"slug":"/how-to-implement-redux-in-react/"}}}]},{"name":"SPA","totalCount":1,"edges":[{"node":{"fields":{"slug":"/Dev-and-prod-ready-Docker-setup-for-SPA-app/"}}}]},{"name":"Slack","totalCount":1,"edges":[{"node":{"fields":{"slug":"/how-does-slack-communicate-with-spotify/"}}}]},{"name":"Spotify","totalCount":1,"edges":[{"node":{"fields":{"slug":"/how-does-slack-communicate-with-spotify/"}}}]},{"name":"Travis","totalCount":2,"edges":[{"node":{"fields":{"slug":"/travis-problematic-python-and-node/"}}},{"node":{"fields":{"slug":"/elasticsearch-script-unknown-field-source-parser-not-found/"}}}]},{"name":"Vue","totalCount":1,"edges":[{"node":{"fields":{"slug":"/Dev-and-prod-ready-Docker-setup-for-SPA-app/"}}}]},{"name":"XDEBUG_CONFIG","totalCount":1,"edges":[{"node":{"fields":{"slug":"/cross-system-xdebug-docker-compose-setup/"}}}]},{"name":"XDebug","totalCount":1,"edges":[{"node":{"fields":{"slug":"/cross-system-xdebug-docker-compose-setup/"}}}]},{"name":"ai","totalCount":1,"edges":[{"node":{"fields":{"slug":"/weekly-ai-bites-last-manual-gap-qa-testing/"}}}]},{"name":"amazon","totalCount":1,"edges":[{"node":{"fields":{"slug":"/minio-as-s3-replacement-in-development-and-beyond/"}}}]},{"name":"apple-watch","totalCount":1,"edges":[{"node":{"fields":{"slug":"/aws-cognito-without-library/"}}}]},{"name":"asp.net core","totalCount":1,"edges":[{"node":{"fields":{"slug":"/net-in-my-browser/"}}}]},{"name":"async","totalCount":2,"edges":[{"node":{"fields":{"slug":"/async-await-with-express/"}}},{"node":{"fields":{"slug":"/complex-command-handler-in-javascript/"}}}]},{"name":"autocomplete","totalCount":1,"edges":[{"node":{"fields":{"slug":"/how-to-write-a-phing-target-autocomplete-bash-script/"}}}]},{"name":"await","totalCount":2,"edges":[{"node":{"fields":{"slug":"/async-await-with-express/"}}},{"node":{"fields":{"slug":"/complex-command-handler-in-javascript/"}}}]},{"name":"aws","totalCount":3,"edges":[{"node":{"fields":{"slug":"/minio-as-s3-replacement-in-development-and-beyond/"}}},{"node":{"fields":{"slug":"/time-out-of-sync-in-aws-ec2/"}}},{"node":{"fields":{"slug":"/aws-cognito-without-library/"}}}]},{"name":"aws.cli","totalCount":1,"edges":[{"node":{"fields":{"slug":"/travis-problematic-python-and-node/"}}}]},{"name":"bash","totalCount":2,"edges":[{"node":{"fields":{"slug":"/cross-system-xdebug-docker-compose-setup/"}}},{"node":{"fields":{"slug":"/how-to-write-a-phing-target-autocomplete-bash-script/"}}}]},{"name":"bitbucket","totalCount":1,"edges":[{"node":{"fields":{"slug":"/how-to-quickly-remove-merged-remote-branches/"}}}]},{"name":"blazor","totalCount":1,"edges":[{"node":{"fields":{"slug":"/net-in-my-browser/"}}}]},{"name":"build","totalCount":1,"edges":[{"node":{"fields":{"slug":"/Dev-and-prod-ready-Docker-setup-for-SPA-app/"}}}]},{"name":"builder pattern","totalCount":1,"edges":[{"node":{"fields":{"slug":"/make-jaxb-great-again/"}}}]},{"name":"c#","totalCount":1,"edges":[{"node":{"fields":{"slug":"/net-in-my-browser/"}}}]},{"name":"ci","totalCount":1,"edges":[{"node":{"fields":{"slug":"/unresolved-check-from-travis-on-github-pull-request/"}}}]},{"name":"claude-code","totalCount":1,"edges":[{"node":{"fields":{"slug":"/weekly-ai-bites-last-manual-gap-qa-testing/"}}}]},{"name":"cognito","totalCount":1,"edges":[{"node":{"fields":{"slug":"/aws-cognito-without-library/"}}}]},{"name":"colors","totalCount":1,"edges":[{"node":{"fields":{"slug":"/naming-sass-color-variables/"}}}]},{"name":"continuous integration","totalCount":1,"edges":[{"node":{"fields":{"slug":"/unresolved-check-from-travis-on-github-pull-request/"}}}]},{"name":"decimal","totalCount":1,"edges":[{"node":{"fields":{"slug":"/mysql-decimal-format/"}}}]},{"name":"docker","totalCount":1,"edges":[{"node":{"fields":{"slug":"/minio-as-s3-replacement-in-development-and-beyond/"}}}]},{"name":"ec2","totalCount":1,"edges":[{"node":{"fields":{"slug":"/time-out-of-sync-in-aws-ec2/"}}}]},{"name":"environment","totalCount":1,"edges":[{"node":{"fields":{"slug":"/Dev-and-prod-ready-Docker-setup-for-SPA-app/"}}}]},{"name":"equals","totalCount":1,"edges":[{"node":{"fields":{"slug":"/jpa-and-uuid/"}}}]},{"name":"flysystem","totalCount":1,"edges":[{"node":{"fields":{"slug":"/minio-as-s3-replacement-in-development-and-beyond/"}}}]},{"name":"front-end","totalCount":1,"edges":[{"node":{"fields":{"slug":"/net-in-my-browser/"}}}]},{"name":"git","totalCount":1,"edges":[{"node":{"fields":{"slug":"/how-to-quickly-remove-merged-remote-branches/"}}}]},{"name":"git commit","totalCount":1,"edges":[{"node":{"fields":{"slug":"/git-not-detecting-renames-quick-workarounds/"}}}]},{"name":"git reflog","totalCount":1,"edges":[{"node":{"fields":{"slug":"/git-reverting-branch-removal/"}}}]},{"name":"git status","totalCount":1,"edges":[{"node":{"fields":{"slug":"/git-not-detecting-renames-quick-workarounds/"}}}]},{"name":"github","totalCount":3,"edges":[{"node":{"fields":{"slug":"/pull-request-templates-on-github/"}}},{"node":{"fields":{"slug":"/unresolved-check-from-travis-on-github-pull-request/"}}},{"node":{"fields":{"slug":"/how-to-quickly-remove-merged-remote-branches/"}}}]},{"name":"guide","totalCount":1,"edges":[{"node":{"fields":{"slug":"/Dev-and-prod-ready-Docker-setup-for-SPA-app/"}}}]},{"name":"hashcode","totalCount":1,"edges":[{"node":{"fields":{"slug":"/jpa-and-uuid/"}}}]},{"name":"hibernate","totalCount":1,"edges":[{"node":{"fields":{"slug":"/jpa-and-uuid/"}}}]},{"name":"java","totalCount":2,"edges":[{"node":{"fields":{"slug":"/make-jaxb-great-again/"}}},{"node":{"fields":{"slug":"/jpa-and-uuid/"}}}]},{"name":"java.time","totalCount":1,"edges":[{"node":{"fields":{"slug":"/make-jaxb-great-again/"}}}]},{"name":"jaxb","totalCount":1,"edges":[{"node":{"fields":{"slug":"/make-jaxb-great-again/"}}}]},{"name":"jdk8","totalCount":1,"edges":[{"node":{"fields":{"slug":"/make-jaxb-great-again/"}}}]},{"name":"jpa","totalCount":1,"edges":[{"node":{"fields":{"slug":"/jpa-and-uuid/"}}}]},{"name":"maven","totalCount":1,"edges":[{"node":{"fields":{"slug":"/make-jaxb-great-again/"}}}]},{"name":"middleware","totalCount":1,"edges":[{"node":{"fields":{"slug":"/how-to-implement-redux-in-react/"}}}]},{"name":"mono","totalCount":1,"edges":[{"node":{"fields":{"slug":"/net-in-my-browser/"}}}]},{"name":"multi-stage","totalCount":1,"edges":[{"node":{"fields":{"slug":"/Dev-and-prod-ready-Docker-setup-for-SPA-app/"}}}]},{"name":"naming","totalCount":1,"edges":[{"node":{"fields":{"slug":"/naming-sass-color-variables/"}}}]},{"name":"networking","totalCount":1,"edges":[{"node":{"fields":{"slug":"/time-out-of-sync-in-aws-ec2/"}}}]},{"name":"ntp","totalCount":1,"edges":[{"node":{"fields":{"slug":"/time-out-of-sync-in-aws-ec2/"}}}]},{"name":"nvm","totalCount":1,"edges":[{"node":{"fields":{"slug":"/travis-problematic-python-and-node/"}}}]},{"name":"persistence","totalCount":1,"edges":[{"node":{"fields":{"slug":"/jpa-and-uuid/"}}}]},{"name":"port 4381","totalCount":1,"edges":[{"node":{"fields":{"slug":"/how-does-slack-communicate-with-spotify/"}}}]},{"name":"pr","totalCount":1,"edges":[{"node":{"fields":{"slug":"/pull-request-templates-on-github/"}}}]},{"name":"production","totalCount":1,"edges":[{"node":{"fields":{"slug":"/Dev-and-prod-ready-Docker-setup-for-SPA-app/"}}}]},{"name":"project","totalCount":1,"edges":[{"node":{"fields":{"slug":"/pull-request-templates-on-github/"}}}]},{"name":"pull","totalCount":1,"edges":[{"node":{"fields":{"slug":"/pull-request-templates-on-github/"}}}]},{"name":"qa","totalCount":1,"edges":[{"node":{"fields":{"slug":"/weekly-ai-bites-last-manual-gap-qa-testing/"}}}]},{"name":"razor","totalCount":1,"edges":[{"node":{"fields":{"slug":"/net-in-my-browser/"}}}]},{"name":"reducer","totalCount":1,"edges":[{"node":{"fields":{"slug":"/how-to-implement-redux-in-react/"}}}]},{"name":"regex","totalCount":1,"edges":[{"node":{"fields":{"slug":"/how-to-write-a-phing-target-autocomplete-bash-script/"}}}]},{"name":"repo","totalCount":1,"edges":[{"node":{"fields":{"slug":"/how-to-quickly-remove-merged-remote-branches/"}}}]},{"name":"repository","totalCount":1,"edges":[{"node":{"fields":{"slug":"/how-to-quickly-remove-merged-remote-branches/"}}}]},{"name":"s3","totalCount":1,"edges":[{"node":{"fields":{"slug":"/minio-as-s3-replacement-in-development-and-beyond/"}}}]},{"name":"sass","totalCount":1,"edges":[{"node":{"fields":{"slug":"/naming-sass-color-variables/"}}}]},{"name":"setup","totalCount":1,"edges":[{"node":{"fields":{"slug":"/Dev-and-prod-ready-Docker-setup-for-SPA-app/"}}}]},{"name":"skills","totalCount":1,"edges":[{"node":{"fields":{"slug":"/weekly-ai-bites-last-manual-gap-qa-testing/"}}}]},{"name":"styles","totalCount":1,"edges":[{"node":{"fields":{"slug":"/naming-sass-color-variables/"}}}]},{"name":"symfony","totalCount":1,"edges":[{"node":{"fields":{"slug":"/minio-as-s3-replacement-in-development-and-beyond/"}}}]},{"name":"templates","totalCount":1,"edges":[{"node":{"fields":{"slug":"/pull-request-templates-on-github/"}}}]},{"name":"test-automation","totalCount":1,"edges":[{"node":{"fields":{"slug":"/weekly-ai-bites-last-manual-gap-qa-testing/"}}}]},{"name":"transaction","totalCount":1,"edges":[{"node":{"fields":{"slug":"/is-mysql-autoincrement-really-monotonic/"}}}]},{"name":"travis","totalCount":1,"edges":[{"node":{"fields":{"slug":"/unresolved-check-from-travis-on-github-pull-request/"}}}]},{"name":"tutorial","totalCount":2,"edges":[{"node":{"fields":{"slug":"/how-to-implement-redux-in-react/"}}},{"node":{"fields":{"slug":"/Dev-and-prod-ready-Docker-setup-for-SPA-app/"}}}]},{"name":"ubuntu","totalCount":1,"edges":[{"node":{"fields":{"slug":"/time-out-of-sync-in-aws-ec2/"}}}]},{"name":"unsupported","totalCount":1,"edges":[{"node":{"fields":{"slug":"/aws-cognito-without-library/"}}}]},{"name":"uuid","totalCount":1,"edges":[{"node":{"fields":{"slug":"/jpa-and-uuid/"}}}]},{"name":"variables","totalCount":1,"edges":[{"node":{"fields":{"slug":"/naming-sass-color-variables/"}}}]},{"name":"wasm","totalCount":1,"edges":[{"node":{"fields":{"slug":"/net-in-my-browser/"}}}]},{"name":"watchos","totalCount":1,"edges":[{"node":{"fields":{"slug":"/aws-cognito-without-library/"}}}]},{"name":"web","totalCount":1,"edges":[{"node":{"fields":{"slug":"/net-in-my-browser/"}}}]}]},"author":{"id":"37bda159-ff45-50c9-aeba-18326b7ca66b","childMarkdownRemark":{"html":"<p><strong>XSolve</strong> We are Agile Software House focused on PHP/Symfony, #JavaScript, #Java and #Mobile (iOS, Android, Windows Phone) #Inc5000 European company in 2018.\n<br>\n<a href=\"https://xsolve.software\">xsolve.software</a></p>"}},"footnote":{"id":"b4474c9b-7be6-5f34-866a-cdfffa885bce","childMarkdownRemark":{"html":"<ul>\n<li>From <a href=\"https://www.boldare.com/\">Boldare</a></li>\n<li>with <a href=\"https://github.com/greglobinski/gatsby-starter-personal-blog/\">Gatsby starter</a></li>\n<li>delivered by <a href=\"https://www.netlify.com/\">Netlify</a></li>\n</ul>"}},"site":{"siteMetadata":{"facebook":{"appId":""}}}},"pageContext":{"slug":"/minio-as-s3-replacement-in-development-and-beyond/"}}