From c55722c79a9defac1101783465883ee58de8b5a1 Mon Sep 17 00:00:00 2001 From: Matthew Rayner Date: Tue, 23 Aug 2016 12:08:09 +0100 Subject: [PATCH] Updated testing and README to be more comprehansive --- .dockerignore | 1 + .gitignore | 1 - README.md | 212 ++++++++++++++++++++++++++++++---------- circle.yml | 18 ++-- docker-compose.test.yml | 16 +++ tests/1404.sh | 9 +- tests/1604.sh | 9 +- tests/Dockerfile.test | 17 ++++ tests/_helpers.sh | 13 ++- tests/test.sh | 25 +---- 10 files changed, 220 insertions(+), 101 deletions(-) create mode 100644 docker-compose.test.yml create mode 100644 tests/Dockerfile.test diff --git a/.dockerignore b/.dockerignore index 444697c..76cdb46 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,6 +1,7 @@ .gitignore CHANGELOG.md circle.yml +docker-compose.test.yml docs/ tests/ LICENSE diff --git a/.gitignore b/.gitignore index 6482e31..485dee6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ .idea -tests/actual diff --git a/README.md b/README.md index 6851c12..cefb81b 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,11 @@ # ![Docker-LAMP][logo] -Docker-LAMP is a docker image that includes the phusion base image, [Apache][apache], [MySQL][mysql] and [PHP][php] all in one handy package. +Docker-LAMP is a set of docker images that include the phusion baseimage (both 14.04 and 16.04 varieties), along with a LAMP stack ([Apache][apache], [MySQL][mysql] and [PHP][php]) all in one handy package. + +With both Ubuntu **16.04** and **14.04** images on the latest-1604 and latest-1404 tags, Docker-LAMP is flexible enough to use with all of your LAMP projects. [![Build Status][shield-build-status]][info-build-status] -[![Dokcer Status][shield-quay]][info-quay] +[![Docker Hub][shield-docker-hub]][info-docker-hub] +[![Quay Status][shield-quay]][info-quay] [![License][shield-license]][info-license] @@ -11,130 +14,230 @@ Docker-LAMP is a docker image that includes the phusion base image, [Apache][apa +- [Introduction](#introduction) - [Component Versions](#component-versions) - [Using the image](#using-the-image) - - [Building from source](#building-from-source) - - [Using with a Dockerfile](#using-with-a-dockerfile) - - [MySQL](#mysql) + - [On the command line](#on-the-command-line) + - [With a Dockerfile](#with-a-dockerfile) + - [MySQL Databases](#mysql-databases) - [Creating a database](#creating-a-database) - [PHPMyAdmin](#phpmyadmin) - [Command Line](#command-line) - [Adding your own content](#adding-your-own-content) - - [Adding your own 'php'](#adding-your-own-php) + - [Adding your app](#adding-your-app) - [Persisting your MySQL](#persisting-your-mysql) - - [Doing both (recommended)](#doing-both-recommended) + - [Doing both](#doing-both) - [`.bash_profile` alias examples](#bash_profile-alias-examples) -- [Credits](#credits) + - [Example usage](#example-usage) +- [Developing the image](#developing-the-image) + - [Building and running](#building-and-running) + - [Testing](#testing) + - [One-line testing command](#one-line-testing-command) + - [`docker-compose -f docker-compose.test.yml -p ci build;`](#docker-compose--f-docker-composetestyml--p-ci-build) + - [`docker-compose -f docker-compose.test.yml -p ci up -d;`](#docker-compose--f-docker-composetestyml--p-ci-up--d) + - [`docker logs -f ci_sut_1;`](#docker-logs--f-ci_sut_1) + - [`echo "Exited with status code: $(docker wait ci_sut_1)"`](#echo-exited-with-status-code-docker-wait-ci_sut_1) +- [Inspiration](#inspiration) +- [Contributing](#contributing) +- [License](#license) +## Introduction +As a developer, part of my day to day role is to build LAMP applications. I searched in vein for an image that had everything I wanted, up-to-date packages, a simple interface, good documentation and active support. + +To complicate things even further I needed an image, or actually two, that would run my applications on both 14.04 and 16.04. Having two entirely separate workflows didn't make any sense to me, and Docker-LAMP was born. + +Designed to be a single interface that just 'gets out of your way', and works on both 14.04 and 16.04, you can move between both bases without changing how you work with Docker. ## Component Versions -Component | Version ----|--- -[Apache][apache] | `2.4.7` -[MySQL][mysql] | `5.5.50-0ubuntu0.14.04.1` -[PHP][php] | `5.5.9-1ubuntu4.19` +Component | 14.04 Version | 16.04 Version +---|---|--- +[Apache][apache] | `2.4.7` | `2.4.18` +[MySQL][mysql] | `5.5.50-0ubuntu0.14.04.1` | `5.7.13-0ubuntu0.16.04.2` +[PHP][php] | `5.5.9-1ubuntu4.19` | `5.6.25-1+deb.sury.org~xenial+1` +[phpMyAdmin][phpmyadmin] | `4.6.4` | `4.6.4` ## Using the image -### Building from source -``` -docker build -t=mattrayner/lamp . -docker run -d -p 80:80 -p 3306:3306 mattrayner/lamp +### On the command line +This is the quickest way +```bash +# Launch a 16.04 based image +docker run -p "80:80" -v ${PWD}/app:/app mattrayner/lamp:latest-1604 + +# Launch a 14.04 based image +docker run -p "80:80" -v ${PWD}/app:/app mattrayner/lamp:latest-1404 ``` -### Using with a Dockerfile -``` -FROM mattrayner/lamp:latest +### With a Dockerfile +```docker +FROM mattrayner/lamp:latest-1604 # Your custom commands CMD ["/run.sh"] ``` -### MySQL -The default image comes with a `root` MySQL account that has no password. This account is only available locally though i.e. within your application. It is not availzble from outside your docker image. +### MySQL Databases +By default, the image comes with a `root` MySQL account that has no password. This account is only available locally, i.e. within your application. It is not available from outside your docker image or through phpMyAdmin. -When you first run the image you'll see a message showing your `admin` user password. This user can be used locally and externally. Either by connecting to port 3306 using a tool like MySQL Workbench or Sequel Pro. If you need this login later, you can run `docker logs CONTAINER_ID` and you should see it at the top of the log. +When you first run the image you'll see a message showing your `admin` user's password. This user can be used locally and externally, either by connecting to your MySQL port (default 3306) and using a tool like MySQL Workbench or Sequel Pro, or through phpMyAdmin. -The image comes pre-installed with PHPMyAdmin available from `/phpmyadmin`. **NOTE:** you cannot use the `root` user with PHPMyAdmin. +If you need this login later, you can run `docker logs CONTAINER_ID` and you should see it at the top of the log. #### Creating a database So your application needs a database - you have two options... + 1. PHPMyAdmin 2. Command line ##### PHPMyAdmin -Simply log in with the details mentioned above and create a database +Docker-LAMP comes pre-installed with phpMyAdmin available from `http://DOCKER_ADDRESS/phpmyadmin`. + +**NOTE:** you cannot use the `root` user with PHPMyAdmin. We recommend logging in with the admin user mentioned in the introduction to this section. ##### Command Line First, get the ID of your running container with `docker ps`, then run the below command replacing `CONTAINER_ID` and `DATABASE_NAME` with your required values: - -``` +```bash docker exec CONTAINER_ID mysql -uroot -e "create database DATABASE_NAME" ``` ## Adding your own content -The 'easiest' way to add your own content to the lamp image is using Docker volumes. This will effectively 'sync' a particular folder on your machine with that on the docker machine. +The 'easiest' way to add your own content to the lamp image is using Docker volumes. This will effectively 'sync' a particular folder on your machine with that on the docker container. The below examples assume the following project layout and that you are running the commands from the 'project root'. - ``` / (project root) /app/ (your PHP files live here) +/mysql/ (docker will create this and store your MySQL data here) ``` -That is to say that your project contains a folder called `app` containing all of your app's code. +In english, your project should contain a folder called `app` containing all of your app's code. That's pretty much it. -### Adding your own 'php' -``` +### Adding your app +The below command will run the docker image `mattrayner/lamp` interactively, exposing port `80` on the host machine with port `80` on the docker container. It will then create a volume linking the `app/` directory within your project to the `/app` directory on the container. This is where Apache is expecting your PHP to live. +```bash docker run -i -t -p "80:80" -v ${PWD}/app:/app mattrayner/lamp ``` -The above will run the docker image `mattrayner/lamp` interactively, exposeing port `80` on the host machine with port `80` on the docker container. It will then create a volume linking `app/` within the project directory to `/app` on the containers file directory. This will load your PHP into apache. - ### Persisting your MySQL -``` +The below command will run the docker image `mattrayner/lamp`, creating a `mysql/` folder within your project. This folder will be linked to `/var/lib/mysql` where all of the MySQL files from container lives. You will now be able to stop/start the container and keep your database changes. + +You may also add `-p 3306:3306` after `-p 80:80` to expose the mysql sockets on your host machine. This will allow you to connect an external application such as SequelPro or MySQL Workbench. +```bash docker run -i -t -p "80:80" -v ${PWD}/mysql:/var/lib/mysql mattrayner/lamp ``` -The above will run the docker image, creating a `mysql/` folder within our project. This folder will contain all of the MySQL files from the docker container. Therefore you will be able to stop/start the container and keep your databases. - -You may also add `-p 3306:3306` after `-p 80:80` to expose the mysql sockets on your host machine. - -### Doing both (recommended) -``` -docker run -i -t -p "80:80" -p "3306:3306" -v ${PWD}/app:/app -v ${PWD}/mysql:/var/lib/mysql mattrayner/lamp:latest +### Doing both +The below command is our 'recommended' solution. It both adds your own PHP and persists database files. We have created a more advanced alias in our `.bash_profile` files to enable the short commands `ldi` and `launchdocker`. See the next section for an example. +```bash +docker run -i -t -p "80:80" -v ${PWD}/app:/app -v ${PWD}/mysql:/var/lib/mysql mattrayner/lamp:latest ``` -The above is our 'recommended' solution. It both adds your own PHP and persists database files. We have created an alias in our `.bash_profile` files to enable the short command `ld` or `launch-docker`. - #### `.bash_profile` alias examples -``` -# Create a helper function to launch docker with overrideable parameters +The below example can be added to your `~/.bash_profile` file to add the alias commands `ldi` and `launchdocker`. By default it will launch the 16.04 image - if you need the 14.04 image, simply change the `docker run` command to use `mattrayner/lamp:latest-1404` instead of `mattrayner/lamp:latest`. +```bash +# A helper function to launch docker container using mattrayner/lamp with overrideable parameters +# +# $1 - Apache Port (optional) +# $2 - MySQL Port (optional - no value will cause MySQL not to be mapped) function launchdockerwithparams { APACHE_PORT=80 - MYSQL_PORT=3306 + MYSQL_PORT_COMMAND="" if ! [[ -z "$1" ]]; then APACHE_PORT=$1 fi if ! [[ -z "$2" ]]; then - MYSQL_PORT=$2 + MYSQL_PORT_COMMAND="-p \"$2:3306\"" fi - docker run -i -t -p "$APACHE_PORT:80" -p "$MYSQL_PORT:3306" -v ${PWD}/app:/app -v ${PWD}/mysql:/var/lib/mysql mattrayner/lamp:latest + docker run -i -t -p "$APACHE_PORT:80" $MYSQL_PORT_COMMAND -v ${PWD}/app:/app -v ${PWD}/mysql:/var/lib/mysql mattrayner/lamp:latest } alias launchdocker='launchdockerwithparams $1 $2' -alias ld='launchdockerwithparams $1 $2' +alias ldi='launchdockerwithparams $1 $2' +``` + +##### Example usage +```bash +# Launch docker and map port 80 for apache +ldi + +# Launch docker and map port 8080 for apache +ldi 8080 + +# Launch docker and map port 3000 for apache along with 3306 for MySQL +ldi 3000 3306 +``` + + +## Developing the image +### Building and running +```bash +# Clone the project from Github +git clone https://github.com/mattrayner/docker-lamp.git +cd docker-lamp + +# Build both the 16.04 image and the 14.04 iamge +docker build -t=mattrayner/lamp:latest -f Dockerfile . +docker build -t=mattrayner/lamp:latest-1404 -f Dockerfile1404 . + +# Run the 14.04 image as a container +docker run -p "3000:80" mattrayner/lamp:latest-1404 -d + +# Sleep to allow the container to boot +sleep 5 + +# Curl out the contents of our new container +curl "http://$(docker-machine ip):3000/" +``` + +### Testing +We use `docker-compose` to setup, build and run our testing environment. It allows us to offload a large amount of the testing overhead to Docker, and to ensure that we always test our image in a consistent way thats not affected by the host machine. + +### One-line testing command +We've developed a single-line test command you can run on your machine within the `docker-lamp` directory. This will test any changes that may have been made, as well as comparing installed versions of Apache, MySQL, PHP and phpMyAdmin against those expected. +```bash +docker-compose -f docker-compose.test.yml -p ci build; docker-compose -f docker-compose.test.yml -p ci up -d; docker logs -f ci_sut_1; echo "Exited with status code: $(docker wait ci_sut_1)"; ``` +So what does this command do? + +#### `docker-compose -f docker-compose.test.yml -p ci build;` +First, build that latest version of our docker-compose images. + +#### `docker-compose -f docker-compose.test.yml -p ci up -d;` +Launch our docker containers (`web1604`, `web1404` and `sut` or *system under tests*) in daemon mode. + +#### `docker logs -f ci_sut_1;` +Display all of the logging output from the `sut` container (extremely useful for debugging) + +#### `echo "Exited with status code: $(docker wait ci_sut_1)"` +Report back the status code that the `sut` container ended with. + + +## Inspiration +This image was originally based on [dgraziotin/lamp][dgraziotin-lamp], with a few changes to make it compatible with the Concrete5 CMS. + +I also changed the setup to create ubuntu (well, baseimage, but you get what I'm saying) 14.04 and 16.04 images so that this project could be as useful as possible to as many people as possible. + + +## Contributing +If you wish to submit a bug fix or feature, you can create a pull request and it will be merged pending a code review. + +1. Clone/fork it +2. Create your feature branch (git checkout -b my-new-feature) +3. Commit your changes (git commit -am 'Add some feature') +4. Test your changes using the steps in [Testing](#testing) +5. Push to the branch (git push origin my-new-feature) +6. Create a new Pull Request + -## Credits -This image is based on [dgraziotin/lamp][dgraziotin-lamp] with a few changes to make it compatible with Concrete5. +## License +Docker-LAMP is licensed under the [Apache 2.0 License][info-license]. [logo]: https://cdn.rawgit.com/mattrayner/docker-lamp/831976c022782e592b7e2758464b2a9efe3da042/docs/logo.svg @@ -142,13 +245,16 @@ This image is based on [dgraziotin/lamp][dgraziotin-lamp] with a few changes to [apache]: http://www.apache.org/ [mysql]: https://www.mysql.com/ [php]: http://php.net/ +[phpmyadmin]: https://www.phpmyadmin.net/ [info-build-status]: https://circleci.com/gh/mattrayner/docker-lamp +[info-docker-hub]: https://hub.docker.com/r/mattrayner/lamp [info-quay]: https://quay.io/repository/mattrayner/docker-lamp [info-license]: LICENSE [shield-build-status]: https://img.shields.io/circleci/project/mattrayner/docker-lamp.svg +[shield-docker-hub]: https://img.shields.io/badge/docker%20hub-mattrayner%2Flamp-brightgreen.svg [shield-quay]: https://quay.io/repository/mattrayner/docker-lamp/status -[shield-license]: https://img.shields.io/badge/license-MIT-blue.svg +[shield-license]: https://img.shields.io/badge/license-Apache%202.0-blue.svg [dgraziotin-lamp]: https://github.com/dgraziotin/osx-docker-lamp diff --git a/circle.yml b/circle.yml index 15b9d7c..a9c76c8 100644 --- a/circle.yml +++ b/circle.yml @@ -5,29 +5,31 @@ machine: dependencies: override: - docker info - - docker build --no-cache -t=mattrayner/lamp:latest-1604 -f Dockerfile . - - docker tag mattrayner/lamp:latest-1604 mattrayner/lamp:dev-1604 - - docker tag mattrayner/lamp:latest-1604 mattrayner/lamp:latest - - docker tag mattrayner/lamp:latest-1604 mattrayner/lamp:dev - - docker build --no-cache -t=mattrayner/lamp:latest-1404 -f Dockerfile1404 . - - docker tag mattrayner/lamp:latest-1404 mattrayner/lamp:dev-1404 + - docker-compose -f docker-compose.test.yml -p ci build + - docker-compose -f docker-compose.test.yml -p ci up -d test: override: - - pushd tests && . test.sh && popd + - 'docker logs -f ci_sut_1; echo "Exited with status code: $(docker wait ci_sut_1)"; exit $(docker wait ci_sut_1)' deployment: latest: branch: master commands: - docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS + - docker tag ci_web1604:latest mattrayner/lamp:latest + - docker tag ci_web1604:latest mattrayner/lamp:latest-1604 + - docker tag ci_web1404:latest mattrayner/lamp:latest-1404 + - docker push mattrayner/lamp:latest - docker push mattrayner/lamp:latest-1604 - docker push mattrayner/lamp:latest-1404 - - docker push mattrayner/lamp:latest dev: branch: develop commands: - docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS + - docker tag ci_web1604:latest mattrayner/lamp:dev + - docker tag ci_web1604:latest mattrayner/lamp:dev-1604 + - docker tag ci_web1404:latest mattrayner/lamp:dev-1404 - docker push mattrayner/lamp:dev-1604 - docker push mattrayner/lamp:dev-1404 - docker push mattrayner/lamp:dev \ No newline at end of file diff --git a/docker-compose.test.yml b/docker-compose.test.yml new file mode 100644 index 0000000..d456246 --- /dev/null +++ b/docker-compose.test.yml @@ -0,0 +1,16 @@ +sut: + build: tests/. + dockerfile: Dockerfile.test + links: + - web1604 + - web1404 +web1604: + build: . + dockerfile: Dockerfile + ports: + - "3000:80" +web1404: + build: . + dockerfile: Dockerfile1404 + ports: + - "3001:80" \ No newline at end of file diff --git a/tests/1404.sh b/tests/1404.sh index 4ced1e4..b7ae651 100644 --- a/tests/1404.sh +++ b/tests/1404.sh @@ -1,11 +1,4 @@ #!/bin/bash source _helpers.sh -echo "=> Querying image" -mkdir -p actual/ -curl --retry 10 --retry-delay 5 -o actual/1404.html --silent http://localhost:3001 --stderr - -checkstatus $? - -echo "=> Checking against expected values" -diff -q -b actual/1404.html expected/1404.html -checkstatus $? \ No newline at end of file +testimage 1404 web1404 \ No newline at end of file diff --git a/tests/1604.sh b/tests/1604.sh index 17c1371..1573b29 100644 --- a/tests/1604.sh +++ b/tests/1604.sh @@ -1,11 +1,4 @@ #!/bin/bash source _helpers.sh -echo "=> Querying image" -mkdir -p actual/ -curl --retry 10 --retry-delay 5 -o actual/1604.html --silent http://localhost:3000 --stderr - -checkstatus $? - -echo "=> Checking against expected values" -diff -q -b actual/1604.html expected/1604.html -checkstatus $? \ No newline at end of file +testimage 1604 web1604 \ No newline at end of file diff --git a/tests/Dockerfile.test b/tests/Dockerfile.test new file mode 100644 index 0000000..6859d58 --- /dev/null +++ b/tests/Dockerfile.test @@ -0,0 +1,17 @@ +FROM phusion/baseimage +MAINTAINER Matthew Rayner + +RUN apt-get update && apt-get install -yq curl && apt-get clean + +WORKDIR /app + +COPY test.sh /app/test.sh +COPY 1404.sh /app/1404.sh +COPY 1604.sh /app/1604.sh +COPY _helpers.sh /app/_helpers.sh +COPY expected/1404.html /app/expected/1404.html +COPY expected/1604.html /app/expected/1604.html + +RUN mkdir -p actual/ + +CMD ["bash", "test.sh"] diff --git a/tests/_helpers.sh b/tests/_helpers.sh index fadd272..a0c87cb 100644 --- a/tests/_helpers.sh +++ b/tests/_helpers.sh @@ -1,5 +1,5 @@ #!/bin/bash -# A function to echo success or cause an exit if the value passed != 0 +# Echo success or cause an exit if the value passed != 0 function checkstatus { if [ $1 -eq 0 ]; then echo "=> Success" @@ -7,4 +7,15 @@ function checkstatus { echo "=> Failed" exit $1 fi +} + +# Test our image, first curling our container and then checking the result against our expectations +function testimage { + echo "=> Querying image" + curl --retry 10 --retry-delay 5 -o actual/$1.html $2 --stderr - + checkstatus $? + + echo "=> Checking against expected values" + diff -b actual/$1.html expected/$1.html + checkstatus $? } \ No newline at end of file diff --git a/tests/test.sh b/tests/test.sh index 47e30ca..8e14ea8 100644 --- a/tests/test.sh +++ b/tests/test.sh @@ -1,31 +1,12 @@ #!/bin/bash source _helpers.sh -echo Initialising tests - -echo "=> Starting containers" -echo "=> Starting 16.04 image" -CONTAINER_1_ID=$(docker run -d -p 3000:80 mattrayner/lamp:latest-1604) -checkstatus $? - -echo "=> Starting 14.04 image" -CONTAINER_2_ID=$(docker run -d -p 3001:80 mattrayner/lamp:latest-1404) -checkstatus $? - -echo "=> Sleeping to allow boot" -sleep 20 +echo "Testing mattrayner/lamp" +echo "=> Sleeping to allow boot of containers" +sleep 10 echo "=> Testing 16.04 image" . 1604.sh echo "=> Testing 14.04 image" . 1404.sh - -echo "=> Stopping 16.04 image" -docker stop $CONTAINER_1_ID - -echo "=> Stopping 14.04 image:" -docker stop $CONTAINER_2_ID - -echo "=> Cleaning test artifacts" -rm -rf actual/