{"action":"created","comment":{"url":"https://api.github.com/repos/marmelab/marmelab.github.io/pulls/comments/42778530","id":42778530,"diff_hunk":"@@ -0,0 +1,254 @@\n+---\n+layout: post\n+title: \"How-to dump your Docker-ized database on Amazon S3?\"\n+excerpt: \"Using Docker in staging or production environment is great. But what about your data backups? Here is a how-to tutorial to dump your dockerized databases on Amazon S3.\"\n+image: /images/blog/cloud-backup.png\n+author: <a href=\"http://www.jonathan-petitcolas.com\">Jonathan Petitcolas</a>\n+canonical: http://www.jonathan-petitcolas.com/2015/09/28/dump-docker-ized-database-to-amazon-s3.html\n+tags:\n+- Docker\n+- Amazon S3\n+- database\n+---\n+\n+We sometimes use Docker for our staging environments. Who says staging or production\n+also says data backup. Here is a post describing how we regularly upload our database\n+dumps directly from a Docker container to Amazon S3 servers.\n+\n+## Dumping Docker-ized database on host\n+\n+First step is to create a dump of our database. Let's consider we have an\n+`awesomeproject_pgsql` container:\n+\n+``` sh\n+#!/bin/bash\n+\n+# Configuration\n+CONTAINER_NAME=\"awesomeproject_pgsql\"\n+FILENAME=\"awesomeproject-`date +%Y-%m-%d-%H:%M:%S`.sql\"\n+DUMPS_FOLDER = \"/home/awesomeproject/dumps/\"\n+\n+# Backup from docker container\n+docker exec $CONTAINER_NAME sh -c \"PGPASSWORD=\\\"\\$POSTGRES_PASSWORD\\\" pg_dump --username=\\$POSTGRES_USER \\$POSTGRES_USER > /tmp/$FILENAME\"\n+docker cp $CONTAINER_NAME:/tmp/$FILENAME $DUMPS_FOLDER\n+docker exec $CONTAINER_NAME sh -c \"rm /tmp/awesomeproject-*.sql\"\n+```\n+\n+After setting a few configuration variables to ease re-use of this script, we\n+execute via the `docker exec` command a dump of our PSQL database. For a MySQL\n+one, process would be quite the same, just replace `pg_dump` by `mysqldump`. We\n+put the dump into the container `/tmp` folder.\n+\n+Note the `sh -c` command. This way, we can pass a whole command (including file\n+redirections) as a string, without worrying about conflicts between host and\n+container paths.\n+\n+Database credentials are passed via environment variables. Note the `\\` inside\n+the Docker shell command: it is important as we want these variables to be\n+interpreted in the Docker container, not when host interpret the command. In\n+this example, we're using the [official PostGreSQL](https://hub.docker.com/_/postgres/)\n+image from Docker Hub setting these variables at container creation.\n+\n+We then copy the file from the container to the host using the `docker cp`\n+command, and clean the container temporary folder.\n+\n+## Keeping only last backups\n+\n+We generally keep data backups for a week. We then have 7 days to detect some data\n+anomalies and to restore a dump. Some developers prefers to keep another backup\n+per month, but except in very sensitive environment, data are too outdated to be\n+useful. So, let's focus on last 7 days:\n+\n+``` sh\n+# Keep only 7 most recent backups\n+cd $DUMPS_FOLDER && (ls -t | head -n 7 ; ls -t) | uniq -u | xargs --no-run-if-empty rm\n+cd $DUMPS_FOLDER && bzip2 --best $FILENAME\n+```\n+\n+The first command probably looks like voodoo. Let's explicit it. First step, we\n+go into the dumps folder. Note we need to repeat it on all following lines.\n+Indeed, commands are executed each in their own sub-process. Thus, the `cd` only\n+affect current command, on a single line.\n+\n+The `(ls -t | head -n 7 ; ls -t)` command is a parallel command. We actually\n+execute two different commands at the same time, to send their result on the\n+standard output. We list (`ls`) our files by modification time (`-t`), newer\n+first. We then keep the 7 first lines (`head -n 7`).\n+\n+In addition, we also display all available files. So, all files we should keep\n+are displayed twice.\n+\n+Finally, we keep only the unique lines, using `uniq -u`, and `rm` each result.\n+The `--no-run-if-empty` is just to prevent an error when no file needs to be\n+deleted.\n+\n+As we pay Amazon depending of the amount of data stored on S3, we also\n+compress at the maximum our dumps, using `bzip2 --best`. Even if prices are\n+really cheap, it is always worthy to use a single command to save money, isn't it?\n+\n+## Uploading database dumps on Amazon S3\n+\n+Storing dumps on the same machine than databases is not a good idea. Hard disk\n+may crash, user may block itself from connecting because of too restrictive\n+`iptables` rules (true story), etc. So, let's use a cheap and easy-to-use\n+solution: moving our dumps to Amazon S3.\n+\n+For those unfamiliar with Amazon services, S3 should have been called \"Amazon\n+Unlimited FTP Servers\", according to the [AWS in Plain English](https://www.expeditedssl.com/aws-in-plain-english)\n+post. It is used to:\n+\n+> Store images and other assets for websites. Keep backups and share files\n+between services. Host static websites. Also, many of the other AWS services\n+write and read from S3.\n+\n+Of course, you can restrict access to your files, as we are going to configure it.\n+\n+### Creating bucket\n+\n+First step is to create a S3 bucket. You can replace `bucket` by `hosting` for a\n+better understanding. So, log on your [Amazon Web Services (AWS) console](https://console.aws.amazon.com/console/home),\n+and select S3. Then, `Create bucket` and give it a name and locate it.\n+\n+<div class=\"image\">\n+    <img src=\"/images/blog/db-dumps/s3-create-bucket.png\" alt=\"Create a bucket on Amazon S3\" title=\"Create a bucket on Amazon S3\" class=\"responsive\" />\n+</div>\n+\n+Keep defaut values for all others parameters. We are now going to restrict access\n+to our bucket creating a specific user.\n+\n+### Creating restricted access to our bucket\n+\n+This is the only painful step: creating a user with correct permissions to\n+access our bucket. Indeed, our server script needs to connect on AWS. We can of\n+course give it our own root AWS credentials. But, as it is safer to use a\n+low-privileges account instead of `root` on Linux, we are going to create an\n+`awesomeproject` user.\n+\n+So, go on the [IAM service](https://console.aws.amazon.com/iam/home) (`Identity\n+and Access Management`). On the left menu, choose `Policies` and create a new\n+one from scratch. Give it a name, a description, and add the following content:\n+\n+``` json\n+{\n+    \"Version\": \"2015-09-21\",\n+    \"Statement\": [\n+        {\n+            \"Effect\": \"Allow\",\n+            \"Action\": [\n+                \"s3:GetBucketLocation\",\n+                \"s3:ListAllMyBuckets\"\n+            ],\n+            \"Resource\": \"arn:aws:s3:::*\"\n+        },\n+        {\n+            \"Effect\": \"Allow\",\n+            \"Action\": [\n+                \"s3:ListBucket\"\n+            ],\n+            \"Resource\": [\n+                \"arn:aws:s3:::awesomeproject-private\"\n+            ]\n+        },\n+        {\n+            \"Effect\": \"Allow\",\n+            \"Action\": [\n+                \"s3:PutObject\",\n+                \"s3:GetObject\",\n+                \"s3:DeleteObject\"\n+            ],\n+            \"Resource\": [\n+                \"arn:aws:s3:::awesomeproject-private/*\"\n+            ]\n+        }\n+    ]\n+}\n+```\n+\n+This policy allows three operations, respectively:\n+\n+* Listing all buckets available to user (required to connect on S3),\n+* List bucket content on the specified resource,\n+* Write, read and delete permissions on bucket content.\n+\n+<p class=\"image\">\n+    <img src=\"/images/blog/db-dumps/s3-policy.png\" alt=\"Create a Amazon IAM policy\" title=\"Create a Amazon IAM policy\" class=\"responsive\" />\n+</p>\n+\n+Validate the policy and create a new user (in the `Users` menu). Do not forget to\n+save her credentials, as we will never be able to retrieve our secret access key\n+anymore.\n+\n+Finally, select the fresh new user, and attach it to your `AwesomeProjectPrivate`\n+policy. This cumbersome configuration is now completed. Let's write our last\n+lines of Bash.\n+\n+### Uploading our dumps on Amazon S3\n+\n+To upload our files, we use the AWS-CLI tools. Installing them is as simple as:\n+\n+``` sh\n+sudo pip install awscli\n+```\n+\n+After configuring user credentials through the `aws configure` command, we can\n+complete our script with the following lines:\n+\n+``` sh\n+# Configuration\n+BUCKET_NAME=\"awesomeproject-private\"\n+\n+# [...]\n+\n+# Upload on S3\n+/usr/bin/aws s3 sync --delete $DUMPS_FOLDER s3://$BUCKET_NAME\n+```\n+\n+We synchronize our dumps folder (removing obsolete files) to our bucket. Do not\n+forget to use a full path to the AWS binary. Otherwise, you may get some errors\n+when launched from a Cron job.\n+\n+## Final Script\n+\n+For the record, here is the full script:\n+\n+``` sh\n+#!/bin/bash\n+\n+# Configuration\n+CONTAINER_NAME=\"awesomeproject_pgsql\"\n+FILENAME=\"awesomeproject-`date +%Y-%m-%d-%H:%M:%S`.sql\"\n+DUMPS_FOLDER = \"/home/awesomeproject/dumps/\"\n+BUCKET_NAME=\"awesomeproject-private\"\n+\n+# Backup from docker container\n+docker exec $CONTAINER_NAME sh -c \"PGPASSWORD=\\\"\\$POSTGRES_PASSWORD\\\" pg_dump --username=\\$POSTGRES_USER \\$POSTGRES_USER > /tmp/$FILENAME\"\n+docker cp $CONTAINER_NAME:/tmp/$FILENAME $DUMPS_FOLDER\n+docker exec $CONTAINER_NAME sh -c \"rm /tmp/awesomeproject-*.sql\"\n+\n+# Keep only 7 most recent backups\n+cd $DUMPS_FOLDER && (ls -t | head -n 7 ; ls -t) | uniq -u | xargs --no-run-if-empty rm\n+cd $DUMPS_FOLDER && bzip2 --best $FILENAME\n+\n+# Upload on S3\n+/usr/bin/aws s3 sync --delete $DUMPS_FOLDER s3://$BUCKET_NAME\n+```\n+\n+## Cron task\n+\n+Finally, let's cron our script to automatically save our data each day. Add the\n+following file into `/etc/cron.d/awesomeproject`:\n+\n+```\n+# Daily DB backup\n+00 23 * * * awesomeproject /home/ubuntu/awesomeproject/bin/db-save.sh >> /home/ubuntu/cron.out.log 2>&1\n+```\n+\n+It launches the script every day at 11pm as `awesomeproject` user. Rather use","path":"blog/_posts/2015-10-26-dump-docker-ized-database-to-amazon-s3.md","position":246,"original_position":246,"commit_id":"63d1daeb42c1da54237914a55a13cfb46f099739","original_commit_id":"63d1daeb42c1da54237914a55a13cfb46f099739","user":{"login":"fzaninotto","id":99944,"avatar_url":"https://avatars.githubusercontent.com/u/99944?v=3","gravatar_id":"","url":"https://api.github.com/users/fzaninotto","html_url":"https://github.com/fzaninotto","followers_url":"https://api.github.com/users/fzaninotto/followers","following_url":"https://api.github.com/users/fzaninotto/following{/other_user}","gists_url":"https://api.github.com/users/fzaninotto/gists{/gist_id}","starred_url":"https://api.github.com/users/fzaninotto/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fzaninotto/subscriptions","organizations_url":"https://api.github.com/users/fzaninotto/orgs","repos_url":"https://api.github.com/users/fzaninotto/repos","events_url":"https://api.github.com/users/fzaninotto/events{/privacy}","received_events_url":"https://api.github.com/users/fzaninotto/received_events","type":"User","site_admin":false},"body":"s/Rather use absolute paths instead of relative one/Prefer absolute paths to relative ones","created_at":"2015-10-22T17:27:54Z","updated_at":"2015-10-22T17:27:54Z","html_url":"https://github.com/marmelab/marmelab.github.io/pull/74#discussion_r42778530","pull_request_url":"https://api.github.com/repos/marmelab/marmelab.github.io/pulls/74","_links":{"self":{"href":"https://api.github.com/repos/marmelab/marmelab.github.io/pulls/comments/42778530"},"html":{"href":"https://github.com/marmelab/marmelab.github.io/pull/74#discussion_r42778530"},"pull_request":{"href":"https://api.github.com/repos/marmelab/marmelab.github.io/pulls/74"}}},"pull_request":{"url":"https://api.github.com/repos/marmelab/marmelab.github.io/pulls/74","id":48353424,"html_url":"https://github.com/marmelab/marmelab.github.io/pull/74","diff_url":"https://github.com/marmelab/marmelab.github.io/pull/74.diff","patch_url":"https://github.com/marmelab/marmelab.github.io/pull/74.patch","issue_url":"https://api.github.com/repos/marmelab/marmelab.github.io/issues/74","number":74,"state":"open","locked":false,"title":"[RFR] Add Dockerized database dump on S3 post","user":{"login":"jpetitcolas","id":688373,"avatar_url":"https://avatars.githubusercontent.com/u/688373?v=3","gravatar_id":"","url":"https://api.github.com/users/jpetitcolas","html_url":"https://github.com/jpetitcolas","followers_url":"https://api.github.com/users/jpetitcolas/followers","following_url":"https://api.github.com/users/jpetitcolas/following{/other_user}","gists_url":"https://api.github.com/users/jpetitcolas/gists{/gist_id}","starred_url":"https://api.github.com/users/jpetitcolas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jpetitcolas/subscriptions","organizations_url":"https://api.github.com/users/jpetitcolas/orgs","repos_url":"https://api.github.com/users/jpetitcolas/repos","events_url":"https://api.github.com/users/jpetitcolas/events{/privacy}","received_events_url":"https://api.github.com/users/jpetitcolas/received_events","type":"User","site_admin":false},"body":"![image](https://cloud.githubusercontent.com/assets/688373/10642710/65324b08-781f-11e5-94a7-01846cef94e5.png)\r\n","created_at":"2015-10-21T16:13:38Z","updated_at":"2015-10-22T17:27:54Z","closed_at":null,"merged_at":null,"merge_commit_sha":"060765d5dcd3ee95cd1012a07f7b533b6fdde531","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/marmelab/marmelab.github.io/pulls/74/commits","review_comments_url":"https://api.github.com/repos/marmelab/marmelab.github.io/pulls/74/comments","review_comment_url":"https://api.github.com/repos/marmelab/marmelab.github.io/pulls/comments{/number}","comments_url":"https://api.github.com/repos/marmelab/marmelab.github.io/issues/74/comments","statuses_url":"https://api.github.com/repos/marmelab/marmelab.github.io/statuses/63d1daeb42c1da54237914a55a13cfb46f099739","head":{"label":"marmelab:docker_dump","ref":"docker_dump","sha":"63d1daeb42c1da54237914a55a13cfb46f099739","user":{"login":"marmelab","id":3116319,"avatar_url":"https://avatars.githubusercontent.com/u/3116319?v=3","gravatar_id":"","url":"https://api.github.com/users/marmelab","html_url":"https://github.com/marmelab","followers_url":"https://api.github.com/users/marmelab/followers","following_url":"https://api.github.com/users/marmelab/following{/other_user}","gists_url":"https://api.github.com/users/marmelab/gists{/gist_id}","starred_url":"https://api.github.com/users/marmelab/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/marmelab/subscriptions","organizations_url":"https://api.github.com/users/marmelab/orgs","repos_url":"https://api.github.com/users/marmelab/repos","events_url":"https://api.github.com/users/marmelab/events{/privacy}","received_events_url":"https://api.github.com/users/marmelab/received_events","type":"Organization","site_admin":false},"repo":{"id":13563896,"name":"marmelab.github.io","full_name":"marmelab/marmelab.github.io","owner":{"login":"marmelab","id":3116319,"avatar_url":"https://avatars.githubusercontent.com/u/3116319?v=3","gravatar_id":"","url":"https://api.github.com/users/marmelab","html_url":"https://github.com/marmelab","followers_url":"https://api.github.com/users/marmelab/followers","following_url":"https://api.github.com/users/marmelab/following{/other_user}","gists_url":"https://api.github.com/users/marmelab/gists{/gist_id}","starred_url":"https://api.github.com/users/marmelab/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/marmelab/subscriptions","organizations_url":"https://api.github.com/users/marmelab/orgs","repos_url":"https://api.github.com/users/marmelab/repos","events_url":"https://api.github.com/users/marmelab/events{/privacy}","received_events_url":"https://api.github.com/users/marmelab/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/marmelab/marmelab.github.io","description":"marmelab.com website","fork":false,"url":"https://api.github.com/repos/marmelab/marmelab.github.io","forks_url":"https://api.github.com/repos/marmelab/marmelab.github.io/forks","keys_url":"https://api.github.com/repos/marmelab/marmelab.github.io/keys{/key_id}","collaborators_url":"https://api.github.com/repos/marmelab/marmelab.github.io/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/marmelab/marmelab.github.io/teams","hooks_url":"https://api.github.com/repos/marmelab/marmelab.github.io/hooks","issue_events_url":"https://api.github.com/repos/marmelab/marmelab.github.io/issues/events{/number}","events_url":"https://api.github.com/repos/marmelab/marmelab.github.io/events","assignees_url":"https://api.github.com/repos/marmelab/marmelab.github.io/assignees{/user}","branches_url":"https://api.github.com/repos/marmelab/marmelab.github.io/branches{/branch}","tags_url":"https://api.github.com/repos/marmelab/marmelab.github.io/tags","blobs_url":"https://api.github.com/repos/marmelab/marmelab.github.io/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/marmelab/marmelab.github.io/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/marmelab/marmelab.github.io/git/refs{/sha}","trees_url":"https://api.github.com/repos/marmelab/marmelab.github.io/git/trees{/sha}","statuses_url":"https://api.github.com/repos/marmelab/marmelab.github.io/statuses/{sha}","languages_url":"https://api.github.com/repos/marmelab/marmelab.github.io/languages","stargazers_url":"https://api.github.com/repos/marmelab/marmelab.github.io/stargazers","contributors_url":"https://api.github.com/repos/marmelab/marmelab.github.io/contributors","subscribers_url":"https://api.github.com/repos/marmelab/marmelab.github.io/subscribers","subscription_url":"https://api.github.com/repos/marmelab/marmelab.github.io/subscription","commits_url":"https://api.github.com/repos/marmelab/marmelab.github.io/commits{/sha}","git_commits_url":"https://api.github.com/repos/marmelab/marmelab.github.io/git/commits{/sha}","comments_url":"https://api.github.com/repos/marmelab/marmelab.github.io/comments{/number}","issue_comment_url":"https://api.github.com/repos/marmelab/marmelab.github.io/issues/comments{/number}","contents_url":"https://api.github.com/repos/marmelab/marmelab.github.io/contents/{+path}","compare_url":"https://api.github.com/repos/marmelab/marmelab.github.io/compare/{base}...{head}","merges_url":"https://api.github.com/repos/marmelab/marmelab.github.io/merges","archive_url":"https://api.github.com/repos/marmelab/marmelab.github.io/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/marmelab/marmelab.github.io/downloads","issues_url":"https://api.github.com/repos/marmelab/marmelab.github.io/issues{/number}","pulls_url":"https://api.github.com/repos/marmelab/marmelab.github.io/pulls{/number}","milestones_url":"https://api.github.com/repos/marmelab/marmelab.github.io/milestones{/number}","notifications_url":"https://api.github.com/repos/marmelab/marmelab.github.io/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/marmelab/marmelab.github.io/labels{/name}","releases_url":"https://api.github.com/repos/marmelab/marmelab.github.io/releases{/id}","created_at":"2013-10-14T14:41:40Z","updated_at":"2015-09-29T16:59:56Z","pushed_at":"2015-10-21T16:13:38Z","git_url":"git://github.com/marmelab/marmelab.github.io.git","ssh_url":"git@github.com:marmelab/marmelab.github.io.git","clone_url":"https://github.com/marmelab/marmelab.github.io.git","svn_url":"https://github.com/marmelab/marmelab.github.io","homepage":"marmelab.com","size":37077,"stargazers_count":1,"watchers_count":1,"language":"HTML","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":5,"forks":0,"open_issues":5,"watchers":1,"default_branch":"master"}},"base":{"label":"marmelab:master","ref":"master","sha":"7db89adbabe6d244c7d256e2a072914c752667cf","user":{"login":"marmelab","id":3116319,"avatar_url":"https://avatars.githubusercontent.com/u/3116319?v=3","gravatar_id":"","url":"https://api.github.com/users/marmelab","html_url":"https://github.com/marmelab","followers_url":"https://api.github.com/users/marmelab/followers","following_url":"https://api.github.com/users/marmelab/following{/other_user}","gists_url":"https://api.github.com/users/marmelab/gists{/gist_id}","starred_url":"https://api.github.com/users/marmelab/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/marmelab/subscriptions","organizations_url":"https://api.github.com/users/marmelab/orgs","repos_url":"https://api.github.com/users/marmelab/repos","events_url":"https://api.github.com/users/marmelab/events{/privacy}","received_events_url":"https://api.github.com/users/marmelab/received_events","type":"Organization","site_admin":false},"repo":{"id":13563896,"name":"marmelab.github.io","full_name":"marmelab/marmelab.github.io","owner":{"login":"marmelab","id":3116319,"avatar_url":"https://avatars.githubusercontent.com/u/3116319?v=3","gravatar_id":"","url":"https://api.github.com/users/marmelab","html_url":"https://github.com/marmelab","followers_url":"https://api.github.com/users/marmelab/followers","following_url":"https://api.github.com/users/marmelab/following{/other_user}","gists_url":"https://api.github.com/users/marmelab/gists{/gist_id}","starred_url":"https://api.github.com/users/marmelab/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/marmelab/subscriptions","organizations_url":"https://api.github.com/users/marmelab/orgs","repos_url":"https://api.github.com/users/marmelab/repos","events_url":"https://api.github.com/users/marmelab/events{/privacy}","received_events_url":"https://api.github.com/users/marmelab/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/marmelab/marmelab.github.io","description":"marmelab.com website","fork":false,"url":"https://api.github.com/repos/marmelab/marmelab.github.io","forks_url":"https://api.github.com/repos/marmelab/marmelab.github.io/forks","keys_url":"https://api.github.com/repos/marmelab/marmelab.github.io/keys{/key_id}","collaborators_url":"https://api.github.com/repos/marmelab/marmelab.github.io/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/marmelab/marmelab.github.io/teams","hooks_url":"https://api.github.com/repos/marmelab/marmelab.github.io/hooks","issue_events_url":"https://api.github.com/repos/marmelab/marmelab.github.io/issues/events{/number}","events_url":"https://api.github.com/repos/marmelab/marmelab.github.io/events","assignees_url":"https://api.github.com/repos/marmelab/marmelab.github.io/assignees{/user}","branches_url":"https://api.github.com/repos/marmelab/marmelab.github.io/branches{/branch}","tags_url":"https://api.github.com/repos/marmelab/marmelab.github.io/tags","blobs_url":"https://api.github.com/repos/marmelab/marmelab.github.io/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/marmelab/marmelab.github.io/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/marmelab/marmelab.github.io/git/refs{/sha}","trees_url":"https://api.github.com/repos/marmelab/marmelab.github.io/git/trees{/sha}","statuses_url":"https://api.github.com/repos/marmelab/marmelab.github.io/statuses/{sha}","languages_url":"https://api.github.com/repos/marmelab/marmelab.github.io/languages","stargazers_url":"https://api.github.com/repos/marmelab/marmelab.github.io/stargazers","contributors_url":"https://api.github.com/repos/marmelab/marmelab.github.io/contributors","subscribers_url":"https://api.github.com/repos/marmelab/marmelab.github.io/subscribers","subscription_url":"https://api.github.com/repos/marmelab/marmelab.github.io/subscription","commits_url":"https://api.github.com/repos/marmelab/marmelab.github.io/commits{/sha}","git_commits_url":"https://api.github.com/repos/marmelab/marmelab.github.io/git/commits{/sha}","comments_url":"https://api.github.com/repos/marmelab/marmelab.github.io/comments{/number}","issue_comment_url":"https://api.github.com/repos/marmelab/marmelab.github.io/issues/comments{/number}","contents_url":"https://api.github.com/repos/marmelab/marmelab.github.io/contents/{+path}","compare_url":"https://api.github.com/repos/marmelab/marmelab.github.io/compare/{base}...{head}","merges_url":"https://api.github.com/repos/marmelab/marmelab.github.io/merges","archive_url":"https://api.github.com/repos/marmelab/marmelab.github.io/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/marmelab/marmelab.github.io/downloads","issues_url":"https://api.github.com/repos/marmelab/marmelab.github.io/issues{/number}","pulls_url":"https://api.github.com/repos/marmelab/marmelab.github.io/pulls{/number}","milestones_url":"https://api.github.com/repos/marmelab/marmelab.github.io/milestones{/number}","notifications_url":"https://api.github.com/repos/marmelab/marmelab.github.io/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/marmelab/marmelab.github.io/labels{/name}","releases_url":"https://api.github.com/repos/marmelab/marmelab.github.io/releases{/id}","created_at":"2013-10-14T14:41:40Z","updated_at":"2015-09-29T16:59:56Z","pushed_at":"2015-10-21T16:13:38Z","git_url":"git://github.com/marmelab/marmelab.github.io.git","ssh_url":"git@github.com:marmelab/marmelab.github.io.git","clone_url":"https://github.com/marmelab/marmelab.github.io.git","svn_url":"https://github.com/marmelab/marmelab.github.io","homepage":"marmelab.com","size":37077,"stargazers_count":1,"watchers_count":1,"language":"HTML","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":5,"forks":0,"open_issues":5,"watchers":1,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/marmelab/marmelab.github.io/pulls/74"},"html":{"href":"https://github.com/marmelab/marmelab.github.io/pull/74"},"issue":{"href":"https://api.github.com/repos/marmelab/marmelab.github.io/issues/74"},"comments":{"href":"https://api.github.com/repos/marmelab/marmelab.github.io/issues/74/comments"},"review_comments":{"href":"https://api.github.com/repos/marmelab/marmelab.github.io/pulls/74/comments"},"review_comment":{"href":"https://api.github.com/repos/marmelab/marmelab.github.io/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/marmelab/marmelab.github.io/pulls/74/commits"},"statuses":{"href":"https://api.github.com/repos/marmelab/marmelab.github.io/statuses/63d1daeb42c1da54237914a55a13cfb46f099739"}}}}